0% found this document useful (0 votes)
38 views14 pages

HRT Interview Question

Uploaded by

corgi9571
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
38 views14 pages

HRT Interview Question

Uploaded by

corgi9571
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Email Facebook LinkedIn Reddit Twitter  Mark As Completed  Discussion

Home > Data Structures and Algorithms 🚀 > Queues Interview Questions > Understanding the Queue Data Structure and Its Implementations

 One pager cheat sheet

A queue is a collection of items whereby its operations work in a FIFO - First In First Out manner. The two primary
operations associated with them are enqueue and dequeue.

Lesson Objectives: At the end of this lesson, you will be able to:

1. Know what the queue data structure is and appreciate it's real-world use cases.
2. Learn how queues work and their operations.
3. Know and implement queues with two different approaches.

I'm sure all of us have been in queues before-- perhaps at billing counters, shopping centers, or cafes. The first person
in the line is usually serviced first, then the second, third, and so forth.

We have this concept in computer science as well. Take the example of a printer. Suppose we have a shared printer,
and several jobs are to be printed at once. The printer maintains a printing "queue" internally, and prints the jobs in
sequence based on which came first.

Another instance where queues are extensively used is in the operating system of our machines. An OS maintains
several queues such as a job queue, a ready queue, and a device queue for each of the processes. If you're interested,
refer to this link to know more about them.

I hope we've got a solid high-level understanding about what queues are. Let's go ahead and understand how they
work!
How do queues work?
Consider a pipe, perhaps a metal one in your bathroom or elsewhere in the house. Naturally, it has two open ends.
Imagine that we have some elements in the pipe, and we're trying to get them out. There will be one end through
which we have inserted the elements, and there's another end from which we're getting them out. As seen in the
figure below, this is precisely how the queue data structure is shaped.

Unlike the stack data structure that we primarily think of with one "open end", the queue has two open ends: the
front and rear. They have different purposes-- with the rear being the point of insertion and the front being that of
removal. However, internally, the front and rear are treated as pointers. We'll learn more about them in the
subsequent sections programmatically.

Note that the element that got inside first is the initial one to be serviced, and removed from the queue. Hence
the name: First In First Out (FIFO).

Let's test your knowledge. Click the correct answer from the options.
By which principle do queues work for enqueuing or dequeuing an element?

Click the option that best answers the question.

Random choice of elements

First In First Out

Last In First Out

Elements are marked by relevance

Queue operations and Implementation of queues


Similar to how a stack has push and pop operations, a queue also has two pairwise operations:

1. Enqueue: To add elements


2. Dequeue: To remove elements.

Let's move on and cover each.

Click here to check out our lesson on the stack data structure!
1. Enqueue
The enqueue operation, as said earlier, adds elements to your queue from the rear end. Initially, when the queue is
empty, both our front (sometimes called head ) and rear (sometimes called tail ) pointers are NULL .

Now, let's add an element-- say, 'a' to the queue. Both our front and rear now point to 'a' .

Let's add another element to our queue-- 'b' . Now, our front pointer remains the same, whereas the rear pointer
points to 'b' . We'll add another item 'c' and you'll see that that element is also added at the rear end. Note that, a
must somehow point to be internally, and b must point to c .
2. Dequeue
To dequeue means to remove or delete elements from the queue. This happens from the front end of the queue. A
particular element is removed from a queue after it is done being processed or serviced. We cannot dequeue an empty
queue, and we require at least one element to be present in the queue when we want to dequeue . The following figure
explains the dequeuing of our previous queue.

Are you sure you're getting this? Is this statement true or false?
When dequeuing an element, the front pointer points at the last element added to the queue.

Press true if you believe the statement is correct, or false otherwise.

TRUE

FALSE

Implementation
Let's use python for our implementation. In python , queues can be implemented using three different modules from
the python library.

list (using a list or array is generalizable to most languages)


collections.deque (language-specific)
queue.Queue (language-specific)

Using the list class can be a costly affair since it involves shifting of elements for every addition or deletion. This
requires O(n) time. But, with the round-robin technique, even with lists, we can achieve the time complexity of O(1) .
We have shown the implementation below.

Instead, we can also use the 'deque' class, which is a shorthand for 'Double-ended queue' and requires O(1) time,
which is much more efficient.

Let's test your knowledge. Click the correct answer from the options.
Using list to implement a queue in any programming language, has the complexity of:

Click the option that best answers the question.

O(1)

O(n)

So first-- we can quickly implement a queue using a list or array in most languages! This is intuitive given that
they're both linear data structures, and we just need to enforce some constraints on data flow:

1. To enqueue an item in the queue, we can use the list function append .
2. To dequeue an item from the queue, we can use the list function pop(0) .
3. If we want the "top-most" (or last element to be processed) item in the queue, we can get the last index of the
list using the [-1] index operator.

This is by far the easiest approach, but not necessarily the most performant.

cpp csharp go java javascript python

1 // Initialize a queue list


2 queue = [];
3
4 // Add elements
5 queue.push(1);
6 queue.push(2);
7 queue.push(3);
8
9 console.log("Initial queue state:");
10 console.log(queue);
11
12 // Removing elements from the queue
13 console.log("Elements dequeued from queue");
14 console.log(queue.pop());
15 console.log(queue.pop());
16 console.log(queue.pop());
17
18 console.log("Queue after removing elements");
19 console.log(queue);

Note that in C++, I used the standard queue container, which doesn't allow for direct access to its elements. The initial
printout of the queue state is achieved by copying the queue to a temporary one and iterating through it. In the Go
version, I used slices, which provide direct access to the underlying array, making it easier to print the entire queue.

To make this more efficient with lists, we can create a fixed-sized list and use it with two pointers and modular
operations. It will yield a queue with O(1) access and deletion time.

cpp csharp go java javascript python


1 function Queue() {
2 this.items = [];
3 }
4
5 Queue.prototype.enqueue = function (val) {
6 this.items.push(val);
7 };
8
9 Queue.prototype.dequeue = function () {
10 return this.items.shift();
11 };
12
13 // Check if the queue is empty
14 Queue.prototype.isEmpty = function () {
15 return this.items.length == 0;
16 };
17
18 // Get the element at the front of the queue
19 Queue.prototype.peek = function () {
20 return !this.isEmpty() ? this.items[0] : undefined;
21 };
22
23 Queue.prototype.length = function () {
24 return this.items.length;
25 };
26
27 let q = new Queue();
28 console.log(q);

Linked List Implementation


There is another way to implement a queue. This is very similar to the Linked List implementation of stacks we used in
a previous lesson.
 RUN CODE RESET JAVASCRIPT 
xxxxxxxxxx

queue.Dequeue();

1
class Node {

2
constructor(key) {

3
this.Data = key;
4
this.Next = null;

5
}

6
}

8
class Queue {

9
constructor() {

10
this.front = null;

11
this.rear = null;

12
}

13

14
Enqueue(key) {

15
let node = new Node(key);

16

17
if (this.rear === null) {

18
this.front = node;

19
this.rear = node;

20
return;

21
}

22

23
this.rear.Next = node;

24
this.rear = node;

25
}

26
27
Dequeue() {

28
if (this.front === null) {

29
return;

30
}

31

32
let temp = this.front;

33
this.front = this.front.Next;

34

35
if (this.front === null) {

36
this.rear = null;

37
}
Implementation of queue using queue class
Another way of using queues in python is via the queue class available in Queue module. It has numerous functions
and is widely used along with threads for multi-threading operations. It further has FIFO, LIFO, and priority types of
queues. However, we'll implement a simple queue using the queue class of the python library.

The queue class is imported from the Queue module. The queue is initialized using the Queue() constructor. Note that it
accepts a maxsize() argument, specifying an upper boundary of queue size to throttle memory usage.

We use the put() function to add elements to the queue, and the get() function to remove elements from the queue.
Since we have a maxsize check here, we have two other functions to check empty and full conditions. The function
empty() returns a boolean true if the queue is empty and false if otherwise. Likewise, the full() function returns a
boolean true if the queue is full and false if otherwise.

Here, we added elements to the queue and checked for the full condition using q.full(). Since the maxsize is four
and we added four elements, the boolean is set to true .

Later, we removed three elements, leaving one element in the queue. Hence the q.empty() function returned boolean
false.

You can find more functions on deque collections here.

 RUN CODE RESET JAVASCRIPT 

xxxxxxxxxx

1
// JavaScript program to demonstrate the implementation of a queue using an array

3
let q = [];

5
// Initializing a queue with maxsize 4
6
let maxSize = 4;

8
// Enqueue elements to queue

9
q.push('a');

10
q.push('b');

11
q.push('c');

12
q.push('d');

13

14
// Return Boolean for Full Queue

15
console.log("\nFull:", q.length === maxSize);

16

17
// Dequeue elements from queue

18
console.log("\nElements dequeued from the queue");

19
console.log(q.shift());

20
console.log(q.shift());

21
console.log(q.shift());

22

23
// Return Boolean for Empty Queue

24
console.log("\nEmpty:", q.length === 0);

25

26
// Print the size of the queue

27
console.log("\nQueue size:", q.length);
Implementation of queue using deque class
Let's go ahead and utilize a queue along with its operations in python language using the deque class!

The deque class is imported from the collections module. We use append() function to add elements to the queue
and popleft() function to remove elements from the queue.

We can see that after enqueuing, our initial queue looks like this:

SNIPPET

1 Initial queue:
2 deque(['a', 'b', 'c', 'd'])

And after dequeuing, our final queue looks something like this:

SNIPPET

1 Final queue
2 deque(['d'])

You can find more functions on deque collections here.

 RUN CODE RESET JAVASCRIPT 

xxxxxxxxxx

1
// JavaScript program to demonstrate queue implementation using Array

3
let q = [];

5
// Adding/Enqueueing elements to a queue
6
q.push('a');

7
q.push('b');

8
q.push('c');

9
q.push('d');

10

11
console.log("Initial queue:");

12
console.log(q);

13

14
// Removing/Dequeuing elements from a queue

15
console.log("\nElements dequeued from the queue:");

16
console.log(q.shift());

17
console.log(q.shift());

18
console.log(q.shift());

19

20
console.log("\nFinal queue");

21
console.log(q);

You might also like