Data structure and algorithm IV. queue

Posted by cwiddowson on Thu, 10 Mar 2022 05:44:25 +0100

1, Queue

Like a stack, a queue is a linear structure that follows a specific order in which operations are performed. The order is first in first out (FIFO).

Queue structure is actually a linear structure. If further divided from the storage structure of data, the queue structure includes two types.

・ sequential queue structure: that is, a group of memory units with continuous addresses are used to save the data in the queue in turn. The size of the queue can be specified as an array structure in the program.

・ chained queue structure: save the values of each element in the queue in the form of linked list.

Typical queue structure

Queues are widely used, from the job settings of printers to the background tasks of network applications.  

2, Queue operation

The following four basic operations are performed on the queue:

Enqueue: adds an item to the queue. If the queue is full, it is called an overflow condition.

Dequeue: deletes an item from the queue. Items pop up in the same order as they are pushed. If the queue is empty, it is called an underflow condition.

Front: get the first item from the queue.

Rear: get the last item from the queue.

3, Implementation queue

Implemented using java code

1. Array implementation

// Java program for array
// implementation of queue

// A class to represent a queue
class Queue {
	int front, rear, size;
	int capacity;
	int array[];

	public Queue(int capacity)
	{
		this.capacity = capacity;
		front = this.size = 0;
		rear = capacity - 1;
		array = new int[this.capacity];
	}

	// Queue is full when size becomes
	// equal to the capacity
	boolean isFull(Queue queue)
	{
		return (queue.size == queue.capacity);
	}

	// Queue is empty when size is 0
	boolean isEmpty(Queue queue)
	{
		return (queue.size == 0);
	}

	// Method to add an item to the queue.
	// It changes rear and size
	void enqueue(int item)
	{
		if (isFull(this))
			return;
		this.rear = (this.rear + 1)
					% this.capacity;
		this.array[this.rear] = item;
		this.size = this.size + 1;
		System.out.println(item
						+ " enqueued to queue");
	}

	// Method to remove an item from queue.
	// It changes front and size
	int dequeue()
	{
		if (isEmpty(this))
			return Integer.MIN_VALUE;

		int item = this.array[this.front];
		this.front = (this.front + 1)
					% this.capacity;
		this.size = this.size - 1;
		return item;
	}

	// Method to get front of queue
	int front()
	{
		if (isEmpty(this))
			return Integer.MIN_VALUE;

		return this.array[this.front];
	}

	// Method to get rear of queue
	int rear()
	{
		if (isEmpty(this))
			return Integer.MIN_VALUE;

		return this.array[this.rear];
	}
}

// Driver class
public class Test {
	public static void main(String[] args)
	{
		Queue queue = new Queue(1000);

		queue.enqueue(10);
		queue.enqueue(20);
		queue.enqueue(30);
		queue.enqueue(40);

		System.out.println(queue.dequeue()
						+ " dequeued from queue\n");

		System.out.println("Front item is "
						+ queue.front());

		System.out.println("Rear item is "
						+ queue.rear());
	}
}

Disadvantages of array implementation:

1. Static data structure, fixed size.

2. If the queue has a large number of incoming and outgoing operations, we may not be able to insert elements into the queue at some time (when the front and rear indexes increase linearly), even if the queue is empty (this problem can be avoided by using circular queue).

2. Linked list implementation

// A linked list (LL) node to store a queue entry
class QNode {
    int key;
    QNode next;
 
    // constructor to create a new linked list node
    public QNode(int key)
    {
        this.key = key;
        this.next = null;
    }
}
 
// A class to represent a queue
// The queue, front stores the front node of LL and rear stores the
// last node of LL
class Queue {
    QNode front, rear;
 
    public Queue()
    {
        this.front = this.rear = null;
    }
 
    // Method to add an key to the queue.
    void enqueue(int key)
    {
 
        // Create a new LL node
        QNode temp = new QNode(key);
 
        // If queue is empty, then new node is front and rear both
        if (this.rear == null) {
            this.front = this.rear = temp;
            return;
        }
 
        // Add the new node at the end of queue and change rear
        this.rear.next = temp;
        this.rear = temp;
    }
 
    // Method to remove an key from queue.
    void dequeue()
    {
        // If queue is empty, return NULL.
        if (this.front == null)
            return;
 
        // Store previous front and move front one node ahead
        QNode temp = this.front;
        this.front = this.front.next;
 
        // If front becomes NULL, then change rear also as NULL
        if (this.front == null)
            this.rear = null;
    }
}
 
// Driver class
public class Test {
    public static void main(String[] args)
    {
        Queue q = new Queue();
        q.enqueue(10);
        q.enqueue(20);
        q.dequeue();
        q.dequeue();
        q.enqueue(30);
        q.enqueue(40);
        q.enqueue(50);
        q.dequeue();
        System.out.println("Queue Front : " + q.front.key);
        System.out.println("Queue Rear : " + q.rear.key);
    }
}

Topics: Algorithm data structure queue FIFO