3、队列

基本介绍

  1. 队列是一个有序列表,可以用数组或是链表实现。
  2. 遵循先进先出的原则。

数组模拟队列

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

  1. 将尾指针往后移:rear+1 , 当front == rear 【空】

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

队列的图形表示

 数组模拟队列代码实现

package com.atguigu.queue;

import java.util.Scanner;

public class ArrayQueueDemo {
    public void main(String[] args) {
        //测试
        System.out.println("~~~环形队列的案例~~~");
        // 初始化一个队列
        ArrayQueue queue = new ArrayQueue(4);
        char key = ' ';
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        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 value = scanner.nextInt();
                    queue.addQueue(value);
                    break;
                case 'g':
                    try {
                        int res = queue.getQueue();
                        System.out.println("从队列中取出数据为" + res);
                    } catch (Exception e) {
                        // TODO: handle exception
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int res = queue.headQueue();
                        System.out.println("队列头元素值为=" + res);
                    } catch (Exception e) {
                        // TODO: handle exception
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                default:
                    break;
            }

        }

    }
    //使用数组模拟队列 编写一个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;         //指向队列的头部,front指向队列头的前一个位置
            rear = -1;          //指向队列尾,指向队列尾的数据(就是队列的最后一个数据)
        }

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

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

        //添加数据到队列,入队列,从尾部插入
        private void addQueue(int n){
            //添加数据前先判断队列是否为满
            if(isFull()){
                System.out.println("队列已满,无法添加数据~~~~~");
                return;
            }
            rear++;             //队首指针不动,队尾指针后移
            arr[rear] = n;
        }

        //获取队列的数据,出队列,从头部取出
        public int getQueue(){
            //判断队列是否为空
            if(isEmpty()){
                throw new RuntimeException("队列为空,不能读取数据~~~~~");
            }
            front++;            //front后移
            return arr[front];
        }

        //显示队列的所有数据
        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]);
            }
        }

        //显示队列头数据(不是取出数据)
        public int headQueue(){  
            //判断
            if(isEmpty()){
                throw new RuntimeException("队列为空,没有数据~~~~");
            }
            return arr[front + 1];
        }
    }
}

 数据模拟环形队列

  1. 对front变量的含义做出调整:front指向队列的第一个元素,也就是个说arr[front]就是队列的第一个元素,front初始值为0 front=0.
  2. 对rear变量的含义做出调整:rear指向队列的最后一个元素的后面一个位置,因为希望空出一个空间作为约定(如果maxSize设置为4,那么队列的有效数据最多是3个),rear的初始值为0,rear=0.
  3. 队列满的条件是:(rear + 1) % maxSize == front
  4. 队列空的条件是:rear == front
  5. 分析后,队列中有效的数据的个数:(rear + maxSize - front) % maxSize  
//最新版环形数组

package com.atguigu;

import java.util.Scanner;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {
        System.out.println("~~~环形队列的案例~~~");
        // 初始化一个队列
        CircleArrayQueue queue = new CircleArrayQueue(4);
        char key = ' ';
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        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 value = scanner.nextInt();
                queue.addQueue(value);
                break;
            case 'g':
                try {
                    int res = queue.getQueue();
                    System.out.println("从队列中取出数据为" + res);
                } catch (Exception e) {
                    // TODO: handle exception
                    System.out.println(e.getMessage());
                }
                break;
            case 'h':
                try {
                    int res = queue.headQueue();
                    System.out.println("队列头元素值为=" + res);
                } catch (Exception e) {
                    // TODO: handle exception
                    System.out.println(e.getMessage());
                }
                break;
            case 'e':
                scanner.close();
                loop = false;
            default:
                break;
            }

        }
    }
}

// 环形的队列和前面的单向队列有类似的地方,因为我们修改即可
class CircleArrayQueue {
    private int maxSize;
    private int[] arr; // 该数组存放数据,模拟队列
    private int front; // 指向队列头部
    private int rear; // 指向队列的尾部

    public CircleArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];

    }

    // 判断队列满的方法
    // 队列容量空出一个作为约定
    public boolean isFull() {
        // 1 => rear 1
        // 2 => rear 2
        // 3 => rear 3
        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 j = front; j < front + size(); j++) {
            System.out.printf("arr[%d]=%d\n", j % maxSize, arr[j % maxSize]);

        }
    }

    // 求出当前环形队列有几个元素
    // 动脑筋
    // 基础 【问题/需求 ---> 设计算法】
    public int size() {
        // rear = 1
        // front = 0
        // maxSize = 3
        return (rear + maxSize - front) % maxSize;
    }

    // 查看队列的头元素,但是不是改变队列
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列空~");
        }
        // 这里注意,不要去改变fornt 值
        return arr[front];
    }

}

 

posted @ 2020-10-11 22:58  朱_煜  阅读(126)  评论(0编辑  收藏  举报