Array simulation to implement circular queue

Table of contents

Preface

1. What is a queue?

2. Implementation of array simulation of non-circular queue

3. Array simulation of circular queue

Summarize


Preface 

Author: I love eating animal milk the most

Blog content: Simulation implementation of data structure queue

This blog may not be that simple to understand. I will try my best to make it easier to understand. Come and have a look with me next!


1. What is a queue?

A queue is a special linear data structure that follows the First In First Out (FIFO) principle. A queue can be viewed as a queuing data structure, similar to queuing in real life. In a queue, new elements are added to the end of the queue, while elements can be removed from the queue only from the front of the queue.

The eight balls in the picture above are put into the queue in sequence according to their serial numbers. 

Queues have two basic operations: enqueue and dequeue. The enqueue operation adds an element to the end of the queue, while the dequeue operation removes an element from the front of the queue. In addition to enqueue and dequeue operations, queues can also support other operations, such as obtaining the length of the queue, determining whether the queue is empty, etc.

Queue application scenarios: bank queuing case

2. Implementation of array simulation of non-circular queue

Illustration:

Analysis:  The queue itself is an ordered list. If the array structure is used to store the data of the queue, the declaration of the queue array is as shown in the figure above, where maxSize is the maximum capacity of the queue. Because the output and input of the queue are processed from the front and rear ends respectively, two variables front and rear are required to record the subscripts of the front and rear ends of the queue respectively. The front will change with the data output, and the rear will change with the data input. Change

Code:

The basic code is given below. We will implement the enqueuing/dequeuing method separately.

public class QueueDemo {
    private int capacity;
    private int front;
    private int rear;
    private int[] Queue;
    
    public QueueDemo(int capacity){
        this.capacity = capacity;
        Queue = new int[capacity];
        front = -1;
        rear = -1;
    }
}
// Determine whether the queue is full
private Boolean IsFull(){
    return rear == capacity-1;
}

// Determine whether the queue is empty
private Boolean IsEmpty(){
    return rear == front;
}

Queue

 

public void addQueue(int data) throws Exception {
    if(IsFull()){
        throw new RuntimeException("The queue is full and new data cannot be inserted");
    }
    arr[++rear] = data;
}

Dequeue

public void getQueue(){
    if(IsEmpty()){
        throw new RuntimeException("The queue is empty and cannot be dequeued!");
    }
    front++;//front moves backward
}

 Problem analysis: It can be clearly seen that the above queue is not a reusable queue, but the actual queue is reusable, and the ring queue is introduced here.

3. Array simulation of circular queue

The idea is as follows :

1. Adjust the meaning of the front variable: front points to the first element of the queue , that is to say, arr[front] is the first element of the queue.

Initial value of front = 0

2. Adjust the meaning of the rear variable: rear points to the position after the last element of the queue . Because we hope to leave a space as a convention .

Initial value of rear = 0

3. When the queue is full, the condition is  (rear + 1) % maxSize == front [ full ]

4. For the condition that the queue is empty, rear == front is empty

5. When we analyze it like this, the number of valid data in the queue   (rear + maxSize - front) % maxSize   // rear = 1 front = 0

Why leave a space as a convention?

If you don't leave a space as a promise, the conditions for the team to be full and the team to be empty are the same. We can't distinguish whether the team is full or empty, so we need to leave a space as a promise

 

The specific implementation of the code is given below
public class circleQueue {
    private int QueueSize;// 队列容量
    private int front;// 队列首部
    private int rear;// 队列尾部
    private int[] arr;// 该数组用于存放数据,模拟队列

    // 构造器
    public circleQueue(int maxSize){
        QueueSize = maxSize;
        front = 0;// 指向队列头部,指向队列头的第一个位置
        rear = 0;// 指向队列尾部,指向队列尾部最后一个元素的下一个位置
        // 约定预留一个空间,如果不预留空间,满和空的条件将会重合
        arr = new int[maxSize];
    }

    // 判断是否为空
    public boolean isNull(){
        return rear == front;
    }

    // 判断是否已满
    public boolean isFull(){
        return (rear+1)% QueueSize == front;
    }

    // 入队列
    public void addQueue(int n){
        if(isFull()){
            throw new RuntimeException("队列已满,不能在增加数据");
        }
        arr[rear] = n;
        rear = (rear+1)%QueueSize;
    }

    // 出队列
    public int getQueue(){
        if(isNull()){
            throw new RuntimeException("队列为空,不能取数据");
        }
        int value = arr[front];
        front = (front+1)%QueueSize;
        return value;
    }

    // 显示队列
    public void showQueue(){
        if(isNull()){
            throw new RuntimeException("队列为空");
        }
        for (int i = front; i <front+getSize() ; i++) {
            System.out.printf("arr[%d] = %d ",i%QueueSize,arr[i%QueueSize]);
        }
    }

    // 显示队列的头数据(不是取数据)
    public void showHead(){
        if(isNull()){
            throw new RuntimeException("队列为空");
        }
        System.out.println("头数据为"+arr[front]);
    }

    public int getSize(){
        return (rear-front+QueueSize)%QueueSize;
    }
}

Summarize

If you have the conditions, it is better to knock it out. It is one thing to understand it, but it is another thing to knock it out.

Among them, % is the key. You need to understand this by yourself. It is not clear just by typing. Please focus on understanding.

Guess you like

Origin blog.csdn.net/weixin_73869209/article/details/132675876