数据结构与算法(三)环形队列

数组实现环形队列

实现:解决之前单向的问题,让数组达到复用的效果,即:当我们从数组队列中取出了数据,那取出数据后后这个空间可以再次使用

思路分析

首先对rear 和 front的含义做调整

  1. rear:指向队列最后一个元素的后一个位置 初始值为0
  2. front:指向队列的头一个元素 初始值为0

rear 指针指向maxSize - 1时,也就是rear = maxSize - 1时,需要判断rear的前面是否有空闲空间,也就说front是否产生了变化并且已经不在初始的那个位置了

说明:

1.rear指向的位置始终都是没有数据的,目的是预留一个位置作为约定

2.rear和front含义发生调整后,判断队列满的条件是( rear + 1 )% maxsize = front

举例:如上图 rear = 7,front = 0,maxSize =8时 (7+1)%8=0 此时队列满

解释:可以看出当rear跟front相邻时就是队列满的条件,如:

rear front 状态
0 1
1 2
2 3

以此类推可以看出当rear + 1 = front时就可以说队列满,那为什么要%maxsize呢?

rear front 状态
7 0

可以看到rear到达maxsize - 1 时rear + 1= front就不满足了,所以需要取模从而达到数组空间复用的效果

3.判断队列为空的条件是rear = front

扫描二维码关注公众号,回复: 11476996 查看本文章

4.队列中有效数据的个数是(rear + maxsize - front) % maxsize
为什么要取模?答:因为是环形队列,rear有可能指到队列最前面。
打个比方,当rear = 0,maxsize = 4 ,front = 0时,该队列中有多少个有效的数据?
分析:(0 + 3 - 0)% 3 = 0,该队列中有效的数据个数为0个,因为rear = front ,则证明是空队列

代码实现

import java.util.Scanner;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {
        //测试
        //创建一个环形队列
        CircleArray queue = new CircleArray(4); //其队列的有效数据最大是3
        char key = ' ';//接收用户输入
        Scanner scanner = new Scanner(System.in);
        //输出一个菜单
        boolean loop = true;
        while (loop){
            System.out.println();
            System.out.println("s(show):显示队列");
            System.out.println("e(exit):退出程序");
            System.out.println("a(add):添加数据到队列");
            System.out.println("g(get):从队列取出数据");
            System.out.println("h(head):查看数据头数据");
            key = scanner.next().charAt(0);
            switch (key){
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("输出一个数字");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    break;
                case 'g':
                    try {
                        int result = queue.getQueue();
                        System.out.println("取出的数据:"+result);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int result = queue.headQueue();
                        System.out.println("队列头的数据是:"+result);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
            }
        }
        System.out.println("程序退出!");
    }
}


class CircleArray{
    private int maxSize;//表示数组的最大容量
    private int front;//队列头,初始值0  指向队列的第一个元素
    private int rear;//队列尾,初始值0  指向最后一个元素的后一个位置
    private int[] arr;//该数组用于存放数据,模拟队列

    public CircleArray(int arrMaxSize){
        maxSize = arrMaxSize;
        //初始化数组
        arr = new int[maxSize];
        front = 0;
        rear = 0;
    }

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

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

    /**
     * 添加数据到队列
     */
    public  void addQueue(int n){
        if(isFull()){
            System.out.println("队列已满!");
            return;
        }
        arr[rear] = n ;
        //将rear后移,这里必须考虑取模
        rear = (rear + 1)% maxSize;
    }

    /**
     * 获取队列的数据,出队列
     */
    public int getQueue(){
        if(isEmpty()){
            throw  new RuntimeException("队列空,不能取数据");
        }
        //front指向队列的第一个元素
        //1.先把front对应的值保留到一个临时变量
        //2.将front后移 考虑取模
        //3.将临时保存的变量返回
        int value = arr[front];
        front = (front+1)%maxSize;
        return value;
    }

    /**
     * 显示队列数据
     */
    public void showQueue(){
        if(isEmpty()){
            System.out.println("队列空");
            return;
        }
        //从front开始遍历
        for(int i = front ;i<front+getSize();i++){
            System.out.println(arr[i%maxSize]);
        }
    }

    /**
     * 当前队列有效数据的个数
     */
    public int getSize(){
        return (rear + maxSize - front)% maxSize;
    }

    /**
     * 显示队列的头数据  注意不是取数据
     */
    public int headQueue(){
        if(isEmpty()){
            throw  new RuntimeException("队列空,没有数据");
        }
        return arr[front];
    }
}

总结

  1. 环形队列判满条件:(rear +1) % maxsize == front
  2. 环形队列判空条件:rear == front
  3. 环形队列有效数据的个数 (rear + maxsize - front) % maxsize
  4. 环形队列中rear的含义:指向队列中最后一个数据的前一个位置,因为要预留一个空间作为约定
  5. 环形队列中front的含义:指向队列头(即:队列中的第一个数据)

猜你喜欢

转载自blog.csdn.net/weixin_47254987/article/details/107608703