当前位置:   article > 正文

【数据结构与算法】顺序队列与环形队列_设计一个算法,将一个环形队列(容量为 n,元素下标从 0 到 n-1)的元素倒置

设计一个算法,将一个环形队列(容量为 n,元素下标从 0 到 n-1)的元素倒置

顺序队列

1 应用场景

银行排队、餐厅网上叫号系统使用的都是队列这种数据结构。

2 基本概念

(1)基本介绍

  • 队列是一个有序列表,可以用数组或是链表来实现,只允许在一端进行插入,在另一端删除。
  • 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
  • 队列示意图如下:

在这里插入图片描述

(2)队列的顺序实现

使用数组模拟队列示意图:

在这里插入图片描述

(3)队列的入队和出队操作

队列本身是有序列表, 其中 maxSize 是该队列的最大容量。例如当队列最大长度MaxSize=5时:

在这里插入图片描述

约定rear总是指向队尾元素,front指向当前队中队头元素的前一位置 。

元素进队,rear增1,元素出队,front增1。

当rear=MaxSize-1时不能再进队。

(4)使用数组模拟队列

存入队列时称为”enQueue”,enQueue 的处理需要有两个步骤:

  • 将尾指针往后移:rear+1 , 当front == rear 【空】
  • 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1[队列满]

3 代码实现

(1)初始化队列

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

(2)判断队列是否已满

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

(3)判断队列是否为空

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

(4)进队

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

(5)出队

// 获取队列元素,出队
public void deQuene(){
    if(!isEmpty()){
        System.out.println(arr[++front]);
        System.out.println("元素:" + arr[front] + "出队成功!");
    }else{
        System.out.println("队列为空,出队失败!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

(6)查看队列中元素

// 输出队列中的所有值
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("队列为空!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

(7)获取队头元素

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

4 完整代码

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("队列为空,无队头元素!");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

二 环形队列

1 基本概念

使用顺序队列有一个问题:当队满之后,经过几次出队操作后,队列中虽然存在空位置,但是不能执行进队操作,具体情形如下图:

在这里插入图片描述

这是因为采用rear==MaxSize-1作为队满条件的缺陷。当队满条件为真时,队中可能还有若干空位置。

这种溢出并不是真正的溢出,称为假溢出。

解决方案就是把数组的前端和后端连接起来,形成一个环形的顺序表,即把存储队列元素的表从逻辑上看成一个环,称为环形队列或循环队列。

在这里插入图片描述

实际上内存地址一定是连续的,不可能是环形的,这里是通过逻辑方式实现环形队列,也就是将rear++和front++改为:

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

2 环形队列的几种状态

在这里插入图片描述

现在约定rear=front为队空,以下两种情况都满足该条件:
在这里插入图片描述

并约定(rear+1)%MaxSize=front为队满条件

当进队一个元素就到达队头时,就认为队满了。这样做会少放一个元素,牺牲一个元素没关系的

3 环形队列的四要素

队空条件:front = rear

队满条件:(rear+1)%MaxSize = front

进队e操作:rear=(rear+1)%MaxSize; 将e放在rear处

出队操作:front=(front+1)%MaxSize; 取出front处元素e;

在环形队列中,实现队列的基本运算算法与非环形队列类似,只是改为上述4要素即可。

4 代码实现

(1)初始化队列

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

(2)判断队列是否已满

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

(3)判断队列是否为空

// 判断是否为空
public boolean isEmpty(){
    return rear == front;
}
  • 1
  • 2
  • 3
  • 4

(4)进队

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

(5)出队

// 出队
public void deQuene(){
    if(!isEmpty()){
        System.out.println("元素:" + arr[front++] + "出队成功!");
        front = front % maxSize;
    }else{
        System.out.println("队列为空,出队失败!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

(6)查看队列中的元素

// 输出队列中的元素
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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

(7)求队列中元素个数

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

(8)获得头元素

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

5 完整代码

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]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/660821
推荐阅读
相关标签
  

闽ICP备14008679号