Queue is a linear datastructure that stores elements with first in first out(FIFO) ordering. That is, the element which gets added to the queue leaves before all the elements added after it.

The most typical example is a real world queue, where you line to get into a public transit or at a movie theater, people get out of the queue prior to all the others who enter after them.

Queue is one of the most used data structure in computer science and is used in various operations or algorithms like,

- CPU Scheduling Algorithms
- Tree Traversals
- Process Synchronization or Message Delivery Systems

Most of the modern day systems communicate with each other using message queues where one system enqueue's or inserts the message to the queue and other system listens to it and deque's the message. There are various implementations of this type like Apache Kafka, Rabbit MQ, IBM MQ etc.

Queue data structure provides the following methods,

**Enqueue**

Adds a element to the rear of the queue**Deque**

Removes the element at the front of the queue**isEmpty**

Returns true if queue is empty or false if it's not**Front**

Returns the front element of the queue**Rear**

Returns the rear element of the queue.

###### Implementation

A queue is typically implemented using an array or linked list. When you use an array, the elements has to be moved during enqueue or deque operations to make room for the new elements which can be expensive.

Ideally we will need a constant operation time for inserting and deleting which can be acheived by using a linked list with references available to head and end of the tail.

Using a linked list, we will use the below psuedo code for various queue operations,

###### Psuedo Code

**Enqueue**`if tail is null create new node, assign head and tail to it else create a new node, assign its next to tail assign tail to the new node`

**Deque**`if head is null return null else store the head value in a temp assign head to it's next return temp value`

**isEmpty**

```
return if head is null
```

**Front**

```
if head is null
return null
else
return head's value
```

**Rear**

```
if rear is null
return null
else
return rear's value
```

Below is the full java implementation of queue using linkedlist,

```
/*
* Author: Venkatesh,Thallam
*
* Queue data structure implementation using single linked list
*/
/*
* Node Definition for the underlying linked list we use to implement stack
* */
class Node {
int val;
Node next;
Node(int val) {
this.val = val;
}
}
public class QueueImplementation {
Node head, tail;
QueueImplementation() {
head = null;
tail = null;
}
public static void main(String[] args) {
QueueImplementation queue = new QueueImplementation();
queue.enqueue(10);
queue.enqueue(15);
queue.enqueue(25);
queue.dequeue();
System.out.println("queue front is " + queue.front());
System.out.println("queue rear is " + queue.rear());
System.out.println("queue size is " + queue.size());
queue.dequeue();
queue.dequeue();
System.out.println("queue size is " + queue.size());
}
/*
* Adds an element to the rear of the queue
*/
public void enqueue(int val) {
if (tail == null) {
head = tail = new Node(val);
} else {
Node newnode = new Node(val);
tail.next = newnode;
tail = newnode;
}
}
/*
* Removes an element at the front of the queue and returns the element
*/
public Integer dequeue() {
if (head != null) {
head = head.next;
}
return null;
}
/*
* Checks if the queue is empty or has elements.
*/
public boolean isEmpty() {
return head == null;
}
/*
* Returns the number of elements of the queue
*/
public int size() {
int count = 0;
Node temp = head;
while (temp != null) {
count++;
temp = temp.next;
}
return count;
}
/*
* Returns the front element of the queue
*/
public Integer front() {
if (head != null)
return head.val;
else
return null;
}
/*
* Returns the rear element of the queue.
*/
public Integer rear() {
if (tail != null)
return tail.val;
else
return null;
}
}
```

###### Time Complexity

The time complexity for each of the queue operations is below,

- Enqueue - O(1)
- Deque - O(1)
- isEmpty - O(1)
- Front - O(1)
- Rear - O(1)
- Size - O(n), since this requires checking all values of stack.