数据结构小白之队列与环形队列的模拟

队列的简单介绍:

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

使用数组来模拟队列

  1. 说明
  2. 实现思路
  3. 示意图
  4. 代码

1.说明

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

*由于队列的输入输出分别从前后端来处理,所以需要两个变量front和rear分别记录队列的前后端的下标,front随着数据输出而改变(向上移动),rear随着数据的输入而改变(向上移动)

2.实现思路

将数据存储队列时,将尾指针向后移动,rear+1,将数据输出的时候,front+1进行数据输出,当front==rear(队列空)。

若尾指针rear小于队列的最大下标maxSize-1,则将队列存入rear所指的数组元素中,否则无法存入数据,rear==maxSize-1(队列满)。

3.示意图

在这里插入图片描述

4.代码:

1.建立类和构造器

class ArrayQueue {
    private int maxSize;//数组的最大容量
    private int front;  //指向队列头指针
    private int rear;   //指向队列尾指针
    private int[] arr;   //该数组用于存放数据

    //创建队列的构造器
    public ArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1;//指向队列头部,此时指向队列头的前一个位置
        rear = -1;//指向队列的尾部,此时指向队列的最后一个位置
    }

2.判断队列是否为空或者为满

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

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

3.入队列

//添加数据
public void addQueue(int n) {
    //判断队列是否满
    if (isFull()) {
        System.out.println("队列已满,不能加入数据");
        return;
    }
    rear++;//加入数据 尾指针后移
    arr[rear] = n;
}

4.出队列

//出队列(获取队列数据)
public int getQueue() {
    if (isEmpty()) {
        throw new RuntimeException("队列已空,不能取出数据");
    }
    front++;

    return arr[front];
}

5.显示队列以及队列的头数据

扫描二维码关注公众号,回复: 9322989 查看本文章
//显示队列
public void showQueue() {
    if (isEmpty()) {
        System.out.println("队列为空,没有数据");
        return;
    }
    //printf用来进行输入各种占位符
    for(int i=0;i<arr.length;i++){
        System.out.printf("arr[%d]=%d\n",i,arr[i]);
    }
}

//显示队列的头数据
public int headQueue() {
    if (isEmpty()) {
        throw new RuntimeException("队列为空");
    }
    return arr[front + 1];
}

6.主函数测试

public static void main(String[] args) {
    //创建一个队列
    ArrayQueue arrayQueue = 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':
                arrayQueue.showQueue();
                break;
            case 'a':
                System.out.println("请输入一个数据:");
                int value=scanner.nextInt();
                arrayQueue.addQueue(value);
                break;
            case 'g':
                try {
                    int res=arrayQueue.getQueue();
                    System.out.printf("取出的数据是%d\n",res);
                }catch (Exception e){
                    System.out.println(e.getMessage());
                }
                break;

            case 'h':
               try {
                   int res=arrayQueue.headQueue();
                   System.out.printf("队列头的数据是%d\n",res);
               }catch (Exception e){
                   System.out.println(e.getMessage());
               }
                break;
            case 'e':
                scanner.close();
                loop=false;
                break;
        }
    }
    System.out.println("程序退出");
}

注意:由于使用数组去模拟普通队列,只能使用一次,所以需要将普通队列改进为环形队列


数组模拟环形队列

思路如下:
1.front变量的含义做一个调整:front就指向数组队列的第一个元素(原先指向第一个元素的前一个位置),也就是说arr[front]是队列的第一个元素

2.rear指向队列的最后一个元素的后一个位置(原先指向最后一个元素),因为希望空出一个空间做一个约定

3.当队列满时,条件时(rear+1)%maxSize=front【首尾是否重合】

4.队列为空时,rear==front

5.front的初始值为0.rear的初始值为0

6.队列中有效的个数 (rear+maxSize-front)%maxSize

测试一下:
在这里插入图片描述

因此可以修改上述代码如下:

package com.lz.arrayqueue;

import java.util.Scanner;

/***
 * 环形数组实现队列的多次使用
 */
public class CircleArrayQueue {
//测试函数
    public static void main(String[] args) {
        //创建一个队列
        System.out.println("测试数组模拟环形队列的案例~");
        //最大有效数据为3(0--2)
        CircleArray arrayQueue = new CircleArray(4);
        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':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("请输入一个数据:");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;
                case 'g':
                    try {
                        int res = arrayQueue.getQueue();
                        System.out.printf("取出的数据是%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;

                case 'h':
                    try {
                        int res = arrayQueue.headQueue();
                        System.out.printf("队列头的数据是%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
            }
        }
        System.out.println("程序退出");
    }

}

//编写一个CircleArray的类
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对应的值保存到一个临时变量 然后将front后移
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    //显示队列
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空,没有数据");
            return;
        }
        //printf用来进行输入各种占位符
        //从front开始遍历 遍历多少个元素 当前有效元素:(rear+maxSize-front)%maxSize
        for (int i = front; i < front + size(); 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];
    }
}





发布了193 篇原创文章 · 获赞 70 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/Lzinner/article/details/94554733
今日推荐