《大话数据结构》----队列-----数组存储(循环队列)实现--java

队列

是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
队列是一种先进先出(First In First Out)的线性表,简称FIFO.允许插入的一段成为队尾,允许删除的一段为队头

数组的存储改进思路

  • 思考:
    在以往的数组中,N个元素,下标为0即为队头,入队时间复杂度O(1),但是取出时,意味着后续所有元素需要"平移",时间复杂度为O(n),现实中也是如此啊,一群人排队,第一个人走了,后面的人依次向前挪挪.

  • 改进1:
    为什么出队列时一定要全部移动呢,如果不去限制队列的元素必须在存储在数组的前n个单元这一条街,出队性能就会大大增加,也就是说队头不一定在下标为0的位置
    队头不一定为0
    这样一来引入两个指针,front指向队头元素,rear指向队尾元素的下一个位置,这样front==rear时就是空队列.

这样其实还有弊端,简单说单方向都依次递增,前面可能有空单元,但是两个指针挪到后面没地方了,
截图君上场,看后两个图或者后两段就行
假溢出

循环队列

针对假溢出的现象,就再从头开始,也就是头尾相接的循环,我们把队列这种头尾项链的顺序存储结构称为循环队列

循环1
循环2
主要看2

啊…还有一点比较繁琐,就是文中一个关键的点,也是就是怎么计算队列满的方法,有那么一点点废脑袋,当然我的代码中也用了自己的方法来判断.这个耐下心来细细琢磨也就那么回事
还是老样子,截图君上场,
判断1判断2
前期的工作铺垫完毕,到了代码环节

代码实现

package com.company;

/**
 * @Author: comfort
 * @Date: 2020/8/3
 */
public class ArrQueueTest {

    public static void main(String[] args) {
        ArrQueueManager arrQueueManager = new ArrQueueManager();
        String data = "31,21,17,16,77,99,88";
        arrQueueManager.init(data.split(","));
        arrQueueManager.out("初始化");
        arrQueueManager.add(100);
        arrQueueManager.add(120);
        arrQueueManager.out("添加了俩个数以后");
        arrQueueManager.add(130);
        for (int i = 0; i < 5; i++) {
            System.out.print ("取:"+arrQueueManager.get()+" ");
        }
        arrQueueManager.out("\n连续取了5个数后 ");
        arrQueueManager.add(13);
        arrQueueManager.add(42);
        arrQueueManager.add(44);
        arrQueueManager.add(45);
        arrQueueManager.add(46);
        arrQueueManager.add(48);
        arrQueueManager.out("连续添加6个以后");
    }
}

class ArrQueueManager {
    ArrQueue arrQueue = new ArrQueue();

    public int get() {
        //这里判断不一样
        if (arrQueue.front == arrQueue.rear) {
            System.out.println("队列空了");
            return -1;
        }
        int datum = arrQueue.data[arrQueue.front];
        //恢复默认值,只是为了输出好辨别
        arrQueue.data[arrQueue.front]=0;
        //书本
//        arrQueue.front=(arrQueue.front + 1)%arrQueue.MAXSIZE;
        int front = arrQueue.front;
        if (front + 1 == arrQueue.MAXSIZE) {
            arrQueue.front=0;
        }else{
            arrQueue.front++;
        }
        return datum;

    }
    public void add(int value) {
        //转了一圈
        if ((arrQueue.rear + 1)%arrQueue.MAXSIZE == arrQueue.front) {
            System.out.println("插入"+value+"错误:队列满了");
            return;
        }
        arrQueue.data[arrQueue.rear] = value;

        //书本
//        arrQueue.rear=(arrQueue.rear + 1)%arrQueue.MAXSIZE;
        //到达对尾
        if (arrQueue.rear + 1 == arrQueue.MAXSIZE) {
            arrQueue.rear = 0;
        }else{
            arrQueue.rear++;
        }
    }

    public void init(String [] data) {
        arrQueue.front = 0;
        arrQueue.rear = 0;
        if (data.length > arrQueue.MAXSIZE) {
            System.out.println("错误:初始化太长了");
            return;
        }
        for (int i = 0; i < data.length; i++) {
            arrQueue.data[i]=Integer.parseInt(data[i]);
            arrQueue.rear++;
        }
    }

    public void out(String string) {
        System.out.println(string+" 队列内容");
        //输出要根据指针输出
        //尾指针 还未到第二轮
        if (arrQueue.front < arrQueue.rear) {
            for (int i = arrQueue.front; i < arrQueue.rear; i++) {
                System.out.print(arrQueue.data[i]+"  ");
            }
        }else{
            for (int i = arrQueue.front; i < arrQueue.MAXSIZE; i++) {
                System.out.print(arrQueue.data[i]+"  ");
            }
            for (int i = 0; i < arrQueue.rear; i++) {
                System.out.print(arrQueue.data[i]+"  ");
            }
        }
        System.out.println("\n整个数组内容");
        for (int datum : arrQueue.data) {
            System.out.print(datum+"  ");
        }
        System.out.println("======>front:"+arrQueue.front+"  rear:"+arrQueue.rear);
    }

}

class ArrQueue {
    public int MAXSIZE = 10;
    int[] data = new int[MAXSIZE];
    /**
     * 头指针
     **/
    int front;
    /**
     * 尾指针
     **/
    int rear;
}

中间输出废了一点功夫,总感觉不是那么回事,但是也凑合写出来了,希望以后我能自省找到更好的办法再来优化,也许有大佬提出来更好
老规矩 输出

初始化 队列内容
31  21  17  16  77  99  88  
整个数组内容
31  21  17  16  77  99  88  0  0  0  ======>front:0  rear:7
添加了俩个数以后 队列内容
31  21  17  16  77  99  88  100  120  
整个数组内容
31  21  17  16  77  99  88  100  120  0  ======>front:0  rear:9
插入130错误:队列满了
取:31:21:17:16:77 
连续取了5个数后  队列内容
99  88  100  120  
整个数组内容
0  0  0  0  0  99  88  100  120  0  ======>front:5  rear:9
插入48错误:队列满了
连续添加6个以后 队列内容
99  88  100  120  13  42  44  45  46  
整个数组内容
42  44  45  46  0  99  88  100  120  13  ======>front:5  rear:4

主要内容是在插入130失败以后, 再进行删除,再进行插入
这个时候rear就跑到前面去了.达到循环队列的意义

收获和不足

  • 输出越来越熟练了,主要也懒得想其他的抽象方式

  • 在判断frontrear时没有看书独立思考,没有看书中的方式来判断,当然还是书里的方法香.

  • get时判断怎么为空时,偷了懒直接看书判断逻辑,在此特别记下,虽然看着书front==rear看着简单,可是自己想想也要想一下

  • 在输出时,还是改了两次,拿起来就敲的代码输出内容没有参考意义,还是指针顺着队列来一遍,这样才有对比.

拜了拜.下个文章见

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页