数组模拟队列以及环形队列——Java实现

数组模拟队列

队列本身是有序列表,若使用数组的结构存储队列的数据,则队列数组的声明如下图,其中maxSize是该队列的最大容量

因为队列的输出,输入是分别从前后端来处理,因此需要两个变量front和rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变,如图所示:

在这里插入图片描述

当我们将数据存入队列时称为“addQueue”,addQueue的处理有两个步骤:

思路分析:

1.判断尾指针rear是否小于最大下标maxSize-1

2.若为true,则将尾指针往后移,并将数据存入rear所指的数组元素中:rear+1;若为false,则无法存储

代码实现:

import java.util.Scanner;

public class ArrayQueueDemo {
    public static void main(String[] args) {

        //测试
        ArrayQueue queue = new ArrayQueue(3);
        char key =' ';//接受用户输入
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        //输出一个菜单
        while (loop){
            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 i = scanner.nextInt();
                    queue.addQueue(i);
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                case 'g':
                    try{
                        int i1 = queue.delQueue();
                        System.out.printf("取出的数据%d\n", i1);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try{
                        int i1 = queue.headQueue();
                        System.out.printf("队头的数据%d\n", i1);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出");
    }

    static class ArrayQueue{
        private int maxSize;
        private int head;
        private int tear;
        private int[] array;

        //初始化构建一个队列
        ArrayQueue(int arrayMaxSize){
            maxSize = arrayMaxSize;
            array = new int[maxSize];
            head = -1;
            tear = -1;
        }

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

        //判断队列是否为空
        boolean isEmpty(){
            return head == tear;
        }

        //往队列中添加一个元素
        void addQueue(int num){
            if (isFull()){
                System.out.println("队列已经满了。。");
                return;
            }
            tear++;
            array[tear]=num;
        }

        //从队列中取出一个元素
        int delQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列是空的。。");
            }
            head++;
            return array[head];
        }

        //显示队列的所有数据
        void showQueue(){
            if (isEmpty()){
                System.out.println("队列是空的。。");
                return;
            }
            for (int i=0;i<maxSize;i++){
                System.out.printf("arr[%d]=%d\n", i, array[i]);
            }
        }

        //显示队列头部的元素,不是取出
        int headQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列是空的。。");
            }
            return array[head+1];
        }
    }
}

数组模拟环形队列

分析示意图:

在这里插入图片描述

改变如下:

1.front变量的初始值为0,也就是开始指向队列的第一个元素arr[front]

2.rear变量的初始值为0,并且rear总是指向队列最后一个元素的后一个位置,也就是永远指向一个空的位置,除非队列是满的

3.队列满的条件:(rear + 1)%maxsize == front(对maxsize取模是为了防止下标越界)

比如:maxsize为6时,这时rear指向队列的下标是5最后一个位置为空,当添加一个数据,rear就会往后移,而如果rear+1,则会越界,这时就得进行取模运算(rear + 1)%maxsize,rear指向的是0位置,就能够避免,而且

若没有取出过元素,front也是0不变,这时就可以说是满队列了

4.队列为空的条件:rear == front //刚开始rear =0 front=0 队列为空

5.队列中有效数据的个数:(rear-front+maxsize)%maxsize

本来若是普通队列,有效个数为rear-front;而现在是环形队列(首尾相连),也就是rear所指的下标值可能比front的小,也就是rear在front的前面;所以进行取模运算(rear-front+maxsize)%maxsize可以防止负数的出现

6.往环形队列中添加数据时:rear++变为(rear + 1)%maxsize(对maxsize取模是为了防止下标越界)

7.显示环形队列头部数据时:直接取出front指向的下标的对应值就行了

8.取出环形队列数据时:首先要将当前front指向的数据存储起来,然后再改变front的下标,也要进行取模防止下标越界(front + 1)% maxsize

9.显示队列所有数据时:所有数据的个数为有效数据的个数,并且是从front开始的

10.队列中永远有一个空闲的位置,也就是说最大有效数据的个数为maxsize-1

代码实现:

import java.util.Scanner;

public class CircleArrayQueue {
    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("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 i = scanner.nextInt();
                    queue.addQueue(i);
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                case 'g':
                    try{
                        int i1 = queue.delQueue();
                        System.out.printf("取出的数据%d\n", i1);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try{
                        int i1 = queue.headQueue();
                        System.out.printf("队头的数据%d\n", i1);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出");
    }

    static class CircleArray{
        private int maxSize;
        private int head;
        private int tear;
        private int[] array;

        //初始化构建一个队列
        CircleArray(int arrayMaxSize){
            maxSize = arrayMaxSize;
            array = new int[maxSize];
        }

        //判断队列是否填满
        boolean isFull(){
            return (tear +1)%maxSize == head;
        }

        //判断队列是否为空
        boolean isEmpty(){
            return head == tear;
        }

        //往队列中添加一个元素
        void addQueue(int num){
            if (isFull()){
                System.out.println("队列已经满了。。");
                return;
            }
            array[tear]=num;
            tear = (tear +1)%maxSize;
        }

        //从队列中取出一个元素
        int delQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列是空的。。");
            }
            int i = array[head];
            head = (head +1)%maxSize;
            return i;
        }

        //显示队列的所有数据
        void showQueue(){
            if (isEmpty()){
                System.out.println("队列是空的。。");
                return;
            }
            for (int i=head;i<head + size();i++){
                //下标为i%maxSize,也是为了防止下标越界
                System.out.printf("arr[%d]=%d\n", i%maxSize, array[i%maxSize]);
            }
        }

        //显示队列头部的元素,不是取出
        int headQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列是空的。。");
            }
            return array[head];
        }

        //获取队列的有效数据的个数
        int size(){
            return (tear - head +maxSize)%maxSize;
        }
    }
}

视频链接:https://www.bilibili.com/video/BV1E4411H73v

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值