数组结构和算法--2环绕队列

环绕队列

队列含义:

队列是一个有序列表,可以是 数组或是链表来实现
遵循先入先出的原则,即先存入队列的数据要先取出,后存入的要后取出

数组模拟队列思路
队列本身是有序列表,使用数组的结构来存储队列的数据,maxSize是该队列的最大容量
因为队列的输出,输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,
front会随着数据输出而改变,而rear则是随着数据输入而改变
数组模拟环形队列思路
1front变量的含义做调整,front就指向队列的第一个元素,也就是说arr[front] 就是队列的第一个元素,front的初始值=0
2rear变量的含义做调整,real指向队列的最后一个元素的后一个位置,因为希望空出一个空间做约定,rear的初始值=0
3当队列满时,条件是[rear+1]%maxSize==front
4当队列为空时条件rear==front
5队列中有效的数据个数[rear+maxSize-front]%maxSize

问题1:为什么拿到%maxSize的值

 因为数组是一个环形数组,当数组末尾存满,但数组开头的数据取出时,可以把数据接着存到空位。所以用到%maxSize

front代表的就是数组第一个值,rear代表数组最后一个值,此时的环形数组的坐标不代表它属于开头还是结尾

问题2:空队列rear==front和满队列[rear+1]%maxSize==front条件的不同点:

 按照如上图示,real==front会有两种情况,为空或为满。我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。

 如下图所示,我们就认为此队列已经满了,也就是说,我们不允许上图情况出现。

例子

package com.ujiuye.queue;

import java.util.Scanner;

public class CircleArrayQueue {
    public static void main(String[] args) {
        System.out.println("测试模型队列案例");
        //数组长度为3,但是其中有一个是空的,所以最多能放两个数据
        CircleArray queue = new CircleArray(3);
        Scanner sc = new Scanner(System.in);
        char key= ' ';
        boolean flag = true;
        while(flag) {
            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],查看列头数据");
            System.out.println("==================");
            System.out.println("请输入您要进行的操作(请用缩写字母或英文回复!)");
            key = sc.next().charAt(0);
            switch(key) {
            case 's':
                queue.showQueue();
                break;
            case 'a':
                System.out.println("请添加一个数值");
                int n = sc.nextInt();
                queue.addQueue(n);
                break;
            case 'g':
                try {
                    int res = queue.getQueue();
                    System.out.printf("取出的数值是%d\n",res);
                }catch(Exception e) {
                    System.out.println(e.getMessage());
                }
                break;
            case 'h':
                try {
                    int res = queue.headQueue();
                    System.out.printf("队列头数值是%d\n",res);
                }catch(Exception e) {
                    System.out.println(e.getMessage());
                }
                break;
            case 'e':
                sc.close();
                flag = false;
                break;
            default:
                break;
            }
        }
        
    }
}
class CircleArray{
    //表示数组的最大容量
    private int maxSize;
    //指向队列的第一个元素,arr[front] 就是队列的第一个元素,初始值为0
    private int front;
    //指向队列中的最后一个元素的后一个位置,因为希望空出一个空间做约定,rear的初始值=0
    private int rear;
    //用来存储数据,模拟队列
    private int[] arr;
    public CircleArray(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
    }
    //当队列满时,条件是[rear+1]%maxSize==front
    public boolean isFull() {
        return (rear+1)%maxSize == front;
    }
    //当队列为空时条件rear==front
    public boolean isEmpty() {
        return rear == front;
    }
    //往队列里添加数据
    public void addQueue(int n) {
        //先判断队列是否满了
        if(isFull()) {
            System.out.println("队列已满,请排队");
            return;
        }
        //因为rear表示最后一个元素的后一个位置,肯定是空的,所以直接放进去即可不用加1
        arr[rear] = n;
        //将rear后移,考虑环绕问题,所以用取模 的方式
        rear = (rear+1)%maxSize;
    }
    //从队列中拿数据
    public int getQueue() {
        //先判断队列是否为空
        if(isEmpty()) {
            //抛异常不用return
            throw new RuntimeException("队列为空,暂无数值");
        }
        //取队列中的第一值
        int value=arr[front];
        //此时要把front后移,保证再次取值拿到的是第一个值,同时考虑环绕问题
        front = (front+1)%maxSize;
        return value;
    }
    //显示队列中的所有值
    public void showQueue() {
        //先判断队列是否为空
        if(isEmpty()) {
            throw new RuntimeException("队列为空,暂无数值");
        }
        //遍历要从第一个数值front开始遍历
        for(int i = front;i<size()+front;i++) {
            System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
        }
    }
    //求出当前列表数据的个数
    public int size() {
        return (rear+maxSize-front)%maxSize;
    }
    //显示队列的头数据
    public int headQueue() {
        if(isEmpty()) {
            throw new RuntimeException("队列为空,暂无数值");
        }
        return arr[front];
    }
}

。。

猜你喜欢

转载自www.cnblogs.com/bai3535/p/12094059.html
今日推荐