尚硅谷02 数据结构与算法_队列、数组模拟环形队列

文章目录

  • 一、数组实现队列
    • 1. 使用场景
    • 2. 队列介绍
    • 3. 分析
    • 4. 代码
  • 二、数组模拟环形队列
    • 1. 环形队列介绍
    • 2. 分析
    • 3. 代码实现

一、数组实现队列

1. 使用场景

有次序的进行操作,先进先出
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第1张图片
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第2张图片

2. 队列介绍

什么是队列:队列是一个有序列表。可以使用数组或列表实现。
遵循:先进先出的原则。队尾入队,队头出队。
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第3张图片

队尾加数据
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第4张图片

3. 分析

队列容量 maxSize:队列中存放数据元素的最大个数
队列前端 front:队头,在第一个数据元素之前
队列后端 rear:队尾,指向最后一个数据元素
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第5张图片
队列操作:
入队:rear+1后,再入队
出队:front+1后,再出队
判断队满:rear+1==maxSize,根据队尾来判断
判断队空:rear == front,根据队头和队尾来判断
打印队列数据:
获取队头数据:
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第6张图片

4. 代码

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第7张图片
创建一个队列类(注意:新建的这个ArrayQueue类是在ArrayQueueDemo这个类的外面)
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第8张图片

队空、队满、添加数据
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第9张图片

可以通过抛出异常来输出提示信息,抛出异常后会自动结束这段代码运行(相当于return)
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第10张图片
获取数据(出队)、显示数据
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第11张图片
获取队头数据
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第12张图片
测试代码(建立一个菜单)
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第13张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第14张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第15张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第16张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第17张图片

测试结果:
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第18张图片

使用数组存储队列数据存在的问题:数组不能重复使用(只能使用一次)
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第19张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第20张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第21张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第22张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第23张图片

完整代码:

package com.Queue_02;

import java.util.Scanner;

public class ArrayQueueDemo {
    /**
     * 1. 创建一个ArrayQueue类,用数组来模拟队列
     * 2. 添加属性
     * 3. 添加构造方法,初始化属性
     * 4. 判断队空
     * 5. 判断队满
     * 6. 添加数据(入队)
     * 7. 获取数据(出队)
     * 8. 显示队列数据
     * 9. 显示队头数据
     * 10. 测试(添加菜单,测试相关队列操作)
     */

    public static void main(String[] args) {
        // 10. 测试(添加菜单,测试相关队列操作)
        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.print("请输入一个数:");
                    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;
                default:
                    break;
            }
        }
        System.out.println("程序退出~~~");
    }
}

// 使用数组模拟队列——编写一个ArrayQueue类
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;
    }
    // 4. 判断队空
    public boolean isEmpty() {
        return rear == front;
    }
    // 5. 判断队满
    public boolean isFull() {
        return rear + 1 == maxSize;
    }
    // 6. 添加数据(入队)
    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("对列已满,不能在加入数据~~~");
            return;
        }
        rear++;
        arr[rear] = n;
    }
    // 7. 获取数据(出队)
    public int getQueue() {
        if (isEmpty()) {
                /*System.out.println("队列已空,不能再取数据");
                return xxx;*/
            throw new RuntimeException("队列已空,不能再取数据");
        }
        front++;
        return arr[front];
    }
    // 8. 显示队列数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空,没有数据可以显示~~~");
            return;
        }
        // 这里显示的是数据里的全部数据
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr[%d] = %d\n", i, arr[i]);
        }
    }
    // 9. 显示队头数据
    public int headQueue() {
        if (isEmpty()) {
            // 在有返回值的情况下,需要显示提示信息,可以通过抛出异常的方式来显示
            // 抛出异常后,直接结束方法的执行
            throw new RuntimeException("队列是空的,没有数据~~~");
        }
        // 这里只是显示,不是获取,队头的位置不能变
        return arr[front+1];
    }
}

二、数组模拟环形队列

1. 环形队列介绍

最大容量 maxSize:队列的最大容量是队列数据总数+1
队头 front:队列中的第一个数据
队尾 rear:队列中最后一个数据的后面一个位置
队空:rear==front
队满:(rear+1)%maxSize == front
队列中有效元素的个数:(rear+maxSize-front)%maxSize
使用环形队列时,数组里多加了一个空位置(作为约定),实际可容纳的最大数据个数 = (数组长度 -1)
尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第24张图片

2. 分析

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第25张图片

注意:

  1. 这里循环队列里有效数据的个数,是用来显示队列信息时做判断用的,i < front + size()。防止当 rear < front 时,无法进行判断。
  2. 循环显示时,数组越界问题。数组下标 i 自动递增即可,通过 i%maxSize 来获取对应下标的数据。

3. 代码实现

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第26张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第27张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第28张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第29张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第30张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第31张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第32张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第33张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第34张图片

尚硅谷02 数据结构与算法_队列、数组模拟环形队列_第35张图片

完整代码:

package com.Queue_02;

import javax.sound.midi.Soundbank;
import java.util.Scanner;

public class CircleArrayQueueDemo {
    /**
     * 1. 创建一个CircleArrayQueue的类
     * 2. 添加属性
     * 3. 写构造方法,初始化属性
     * 4. 判空
     * 5. 判满
     * 6. 向循环队列中添加数据
     * 7. 从循环队列中取数据
     * 8. 显示队列数据
     * 9. 显示队头数据
     * 10. 测试
     */
    public static void main(String[] args) {
        // 10. 测试
        CircleArrayQueue queue = new CircleArrayQueue(3);
        Scanner scanner = new Scanner(System.in);
        char key = ' ';
        boolean loop = true;
        while (loop) {
            System.out.println("s(show):显示队列");
            System.out.println("a(add):向队列中添加数据");
            System.out.println("g(get):从队列中取数据");
            System.out.println("h(head):显示头数据");
            System.out.println("e(exit):退出队列");
            key =  scanner.next().charAt(0);
            switch (key) {
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.print("请输入要添加的数据:" );
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    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':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("退出程序~~~");
    }
}
class CircleArrayQueue{
    // 1. 创建一个CircleArrayQueue的类
    // 2. 添加属性
    private int maxSize;
    private int front;
    private int rear;
    private int[] arr;
    // 3. 写构造方法,初始化属性
    public CircleArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize + 1;
        front = 0;
        front = 0;
        arr = new int[maxSize];
    }
    // 4. 判空
    public boolean isEmpty() {
        return rear == front;
    }
    // 5. 判满
    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }
    // 6. 向循环队列中添加数据
    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("循环数组已满,不能再添加数据~~~");
            return;
        }
        arr[rear] = n;
        rear = (rear + 1) % maxSize;
    }
    // 7. 从循环队列中取数据
    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("循环数组为空,不能再取数据~~~");
        }
        int oFront = front;
        front = (front + 1) % maxSize;
        return arr[oFront];
    }
    // 8. 显示队列数据
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("循环数组为空,没有数据可供显示~~~");
            return;
        }
        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;
    }
    // 9. 显示队头数据
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("循环数组为空,没有任何数据可供显示~~~");
        }
        return arr[front];
    }
}

你可能感兴趣的:(数据结构与算法,算法与数据结构,队列,循环队列)