[Data Structure and Algorithm] Sequence Queue and Ring Queue

a sequential queue

1 Application Scenarios

Bank queuing and restaurant online calling systems all use the data structure of queues.

2 Basic concepts

(1) Basic introduction

  • A queue is an ordered list, which can be implemented as an array or a linked list, and only allows insertion at one end and deletion at the other end.
  • Follow the principle of first in first out. That is: the data stored in the queue first must be taken out first. What is deposited later must be withdrawn later
  • The queue diagram is as follows:

insert image description here

(2) Sequential implementation of queues

Schematic diagram of using an array to simulate a queue:

insert image description here

(3) Queue entry and exit operations

The queue itself is an ordered list, where maxSize is the maximum capacity of the queue. For example, when the maximum queue length MaxSize=5:

insert image description here

It is agreed that rear always points to the tail element of the queue, and front points to the previous position of the head element in the current queue.

Elements enter the queue, rear increases by 1, elements leave the queue, front increases by 1.

When rear=MaxSize-1, it can no longer enter the team.

(4) Use an array to simulate a queue

When it is stored in the queue, it is called "enQueue". The processing of enQueue requires two steps:

  • Move the tail pointer backward: rear+1, when front == rear 【empty】
  • If the tail pointer rear is smaller than the maximum subscript maxSize-1 of the queue, the data will be stored in the array element pointed to by rear, otherwise the data cannot be stored. rear == maxSize - 1[queue full]

3 code implementation

(1) Initialize the queue

// 执行队列的初始化操作
public ArrayQuene(int maxSize) {
    
    
    this.maxSize = maxSize;
    rear = -1;      // 队尾元素
    front = -1;     // 队头元素
    arr = new int[maxSize];
}

(2) Determine whether the queue is full

// 判断队列是否已满
public boolean isFull(){
    
    
    return rear == maxSize - 1;
}

(3) Determine whether the queue is empty

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

(4) into the team

// 将数据添加到队列
public void enQuene(int data){
    
    
    // 判断队列是否已满
    if(!isFull()){
    
    
        arr[++rear] = data;
        System.out.println("进队成功!");
    } else {
    
    
        System.out.println("队列已满,不能添加数据!");
    }
}

(5) out of the team

// 获取队列元素,出队
public void deQuene(){
    
    
    if(!isEmpty()){
    
    
        System.out.println(arr[++front]);
        System.out.println("元素:" + arr[front] + "出队成功!");
    }else{
    
    
        System.out.println("队列为空,出队失败!");
    }
}

(6) Check the elements in the queue

// 输出队列中的所有值
public void showQuene(){
    
    
    if(!isEmpty()){
    
    
        for(int i = 0; i < arr.length;i++){
    
    
            if(i > front && i <= rear){
    
    
                System.out.print(arr[i] + " ");
            }
    }
    }else{
    
    
        System.out.println("队列为空!");
    }
}

(7) Get the queue head element

// 获取队头元素
public void getHead(){
    
    
    if(!isEmpty()){
    
    
        System.out.println("队头元素为:" + arr[front + 1 ] );
    }else{
    
    
        System.out.println("队列为空,无队头元素!");
    }
}

4 complete code

public static void main(String[] args) {
    
    
    ArrayQuene arrayQuene = new ArrayQuene(5);
    String key = null;
    Scanner sc = new Scanner(System.in);
    boolean index = true;
    while(index){
    
    
        System.out.println("============================");
        System.out.println("show:显示队列");
        System.out.println("en  :进队");
        System.out.println("de  :出队");
        System.out.println("head:显示队头");
        System.out.println("exit:退出程序");
        System.out.println("============================");
        key = sc.nextLine();
        switch (key){
    
    
            case "show":
                arrayQuene.showQuene();
                break;
            case "en":
                System.out.println("请输入进队元素");
                int data = sc.nextInt();
                arrayQuene.enQuene(data);
                break;
            case "de":
                arrayQuene.deQuene();
                break;
            case "head":
                arrayQuene.getHead();
                break;
            case "exit":
                sc.close();
                index = false;
                break;
            default:
                break;
        }
    }
    System.out.println("程序已退出!");
}

public static class ArrayQuene{
    
    
    private int maxSize;
    private int front;
    private int rear;
    private int[] arr;      // 存储数据的值

    // 执行队列的初始化操作
    public ArrayQuene(int maxSize) {
    
    
        this.maxSize = maxSize;
        rear = -1;      // 队尾元素
        front = -1;     // 队头元素
        arr = new int[maxSize];
    }

    // 判断队列是否已满
    public boolean isFull(){
    
    
        return rear == maxSize - 1;
    }

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

    // 将数据添加到队列
    public void enQuene(int data){
    
    
        // 判断队列是否已满
        if(!isFull()){
    
    
            arr[++rear] = data;
            System.out.println("进队成功!");
        } else {
    
    
            System.out.println("队列已满,不能添加数据!");
        }
    }

    // 获取队列元素,出队
    public void deQuene(){
    
    
        if(!isEmpty()){
    
    
            System.out.println(arr[++front]);
            System.out.println("元素:" + arr[front] + "出队成功!");
        }else{
    
    
            System.out.println("队列为空,出队失败!");
        }
    }

    // 输出队列中的所有值
    public void showQuene(){
    
    
        if(!isEmpty()){
    
    
            for (int i : arr) {
    
    
                System.out.println(i + " ");
            }
        }else{
    
    
            System.out.println("队列为空!");
        }
    }

    // 获取队头元素
    public void getHead(){
    
    
        if(!isEmpty()){
    
    
            System.out.println("队头元素为:" + arr[front + 1 ] );
        }else{
    
    
            System.out.println("队列为空,无队头元素!");
        }
    }
}

two ring queues

1 Basic concepts

There is a problem with using a sequential queue: when the queue is full, after several dequeue operations, although there are empty positions in the queue, the enqueue operation cannot be performed. The specific situation is as follows:

insert image description here

This is because of the defect of using rear==MaxSize-1 as the full condition of the team. When the team full condition is true, there may be several empty slots in the team.

This kind of overflow is not real overflow, it is called false overflow.

The solution is to connect the front end and the back end of the array to form a circular sequential table, that is, the table storing queue elements is logically regarded as a ring, which is called a circular queue or a circular queue.

insert image description here

In fact, the memory addresses must be continuous and cannot be circular. Here, the circular queue is implemented in a logical way, that is, rear++ and front++ are changed to:

  • rear=(rear+1)%MaxSize
  • front=(front+1)%MaxSize

2 Several states of the ring queue

insert image description here

Now it is stipulated that rear=front is empty, and the following two situations satisfy this condition:
insert image description here

And agreed (rear+1)%MaxSize=front as the team full condition

When one element enters the queue and reaches the head of the queue, the queue is considered full. Doing so will put one less element, and it doesn't matter if you sacrifice an element

3 Four elements of circular queue

Team empty condition: front = rear

Team full condition: (rear+1)%MaxSize = front

Into the queue e operation: rear=(rear+1)%MaxSize; put e at the rear

Dequeue operation: front=(front+1)%MaxSize; take out the element e at the front ;

In the circular queue, the basic operation algorithm to realize the queue is similar to that of the non-circular queue, only the above four elements can be changed.

4 code implementation

(1) Initialize the queue

// 初始化环形队列
public CircleArray(int maxSize){
    
    
    this.maxSize = maxSize;
    // 定义front执行环形队列的第一个元素,而非顺序队列中执行队头的前一个元素,rear同理
    front = 0;
    rear = 0;
    arr = new int[maxSize];
}

(2) Determine whether the queue is full

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

(3) Determine whether the queue is empty

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

(4) into the team

// 进队
public void enQuene(int data){
    
    
    if(!isFull()){
    
    
        // 注意与顺序队列的区别
        arr[rear++] = data;
        rear = rear % maxSize;
        System.out.println("元素:" + data + "进队成功!");
    }else {
    
    
        System.out.println("队列已满,进队失败!");
    }
}

(5) out of the team

// 出队
public void deQuene(){
    
    
    if(!isEmpty()){
    
    
        System.out.println("元素:" + arr[front++] + "出队成功!");
        front = front % maxSize;
    }else{
    
    
        System.out.println("队列为空,出队失败!");
    }
}

(6) Check the elements in the queue

// 输出队列中的元素
public void showQuene(){
    
    
    if(!isEmpty()){
    
    
        // front从零开始
        for(int i = front; i < front + size(); i++) {
    
    
            // 当i大于rear时,说明队列已满且经过出队操作
            // 针对这种情况,输出rear后所有元素
            if ( (i >= front && i < rear) || (i > rear) ) {
    
    
                System.out.print(arr[i % maxSize] + " ");
            }
        }
    }else{
    
    
        System.out.println("队列为空!");
    }
}

(7) Find the number of elements in the queue

// 求出数据中的元素个数,从1开始
public int size(){
    
    
    return (rear + maxSize - front) % maxSize;
}

(8) Get the head element

// 获取头元素
public void getHead(){
    
    
    System.out.println("队头元素为:" + arr[front % maxSize]);
}

5 complete code

package com.hzy.datastructs;

import java.util.Scanner;

public class CircleArrayDemo {
    
    
    public static void main(String[] args) {
    
    
        CircleArray circleArray = new CircleArray(5);
        String key = null;
        Scanner sc = new Scanner(System.in);
        boolean index = true;
        while(index){
    
    
            System.out.println("============================");
            System.out.println("show:显示队列");
            System.out.println("en  :进队");
            System.out.println("de  :出队");
            System.out.println("head:显示队头");
            System.out.println("exit:退出程序");
            System.out.println("============================");
            key = sc.nextLine();
            switch (key){
    
    
                case "show":
                    circleArray.showQuene();
                    break;
                case "en":
                    System.out.println("请输入进队元素");
                    int data = sc.nextInt();
                    circleArray.enQuene(data);
                    break;
                case "de":
                    circleArray.deQuene();
                    break;
                case "head":
                    circleArray.getHead();
                    break;
                case "size":
                    circleArray.size();
                    break;
                case "exit":
                    sc.close();
                    index = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序已退出!");
    }

    public static class CircleArray{
    
    
        private int[] arr;
        private int front;
        private int rear;
        private int maxSize;

        // 初始化环形队列
        public CircleArray(int maxSize){
    
    
            this.maxSize = maxSize;
            // 定义front执行环形队列的第一个元素,而非顺序队列中执行队头的前一个元素,rear同理
            front = 0;
            rear = 0;
            arr = new int[maxSize];
        }

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

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

        // 进队
        public void enQuene(int data){
    
    
            if(!isFull()){
    
    
                // 注意与顺序队列的区别
                arr[rear++] = data;
                rear = rear % maxSize;
                System.out.println("元素:" + data + "进队成功!");
            }else {
    
    
                System.out.println("队列已满,进队失败!");
            }
        }

        // 出队
        public void deQuene(){
    
    
            if(!isEmpty()){
    
    
                System.out.println("元素:" + arr[front++] + "出队成功!");
                front = front % maxSize;
            }else{
    
    
                System.out.println("队列为空,出队失败!");
            }
        }

        // 输出队列中的元素
        public void showQuene(){
    
    
            if(!isEmpty()){
    
    
                // front从零开始
                for(int i = front; i < front + size(); i++) {
    
    
                    // 当i大于rear时,说明队列已满且经过出队操作
                    // 针对这种情况,输出rear后所有元素
                    if ( (i >= front && i < rear) || (i > rear) ) {
    
    
                        System.out.print(arr[i % maxSize] + " ");
                    }
                }
            }else{
    
    
                System.out.println("队列为空!");
            }
        }

        // 求出数据中的元素个数,从1开始
        public int size(){
    
    
            return (rear + maxSize - front) % maxSize;
        }

        // 获取头元素
        public void getHead(){
    
    
            System.out.println("队头元素为:" + arr[front % maxSize]);
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_43923463/article/details/128500596