zoukankan      html  css  js  c++  java
  • 【数据结构】队列-数组模拟队列

    队列介绍

    ​ 队列是一个有序列表,可以用数组或是链表来实现。

    ​ 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

    ​ 示意图:(使用数组模拟队列示意图)

    队列

    数组模拟队列

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

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

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

    思路分析

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

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

    1.rear 是队列最后[含]

    2.front 是队列最前元素[不含]

    数组模拟队列

    出队列操作getQueue

    显示队列的情况showQueue

    查看队列头元素headQueue

    退出系统exit

    package com.doubledumbao.sparsearray.queue;
    
    import java.util.Scanner;
    
    
    /**
     * 测试队列
     */
    public class ArrayQueueDemo {
        public static void main(String[] args) {
    
            Scanner scanner = new Scanner(System.in);
            char key = ' ';//接收用户输入
            ArrayQueue arrayQueue = new ArrayQueue(3);
            boolean loop = true;
            while(loop){
                System.out.println("a(add):添加数据到队列");
                System.out.println("s(show):显示队列");
                System.out.println("e(exit):退出程序");
                System.out.println("g(get):从队列取出数据");
                System.out.println("h(head):查看队列头的数据");
                key = scanner.next().charAt(0);//接收一个字符
                switch (key){
                    case 'a':
                        System.out.println("输入一个数:");
                        int val = scanner.nextInt();
                        try {
                            arrayQueue.addQueue(val);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                        }
                        break;
                    case 's':
                        arrayQueue.showQueue();
                        break;
                    case 'g':
                        try {
                            System.out.println(arrayQueue.getQueue());
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                        }
                        break;
                    case 'h':
                        try {
                            System.out.println(arrayQueue.headQueue());
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                        }
                        break;
                    case 'e':
                        loop = false;
                        scanner.close();
                        break;
                    default:
                        break;
    
                }
    
            }
    
        }
    }
    
    /**
     * 数组模拟队列
     */
    class ArrayQueue{
        //队列容量
        private int maxSize;
        //队列前端的下标
        private int front;
        //队列后端的下标
        private int rear;
        //存储数据
        private int[] arr;
    
        public ArrayQueue(int maxSize){
            this.maxSize = maxSize;
            this.front = -1;
            this.rear= -1;
            this.arr = new int[maxSize];
        }
    
        /**
         * 判断队列是否满了
         * @return
         */
        public boolean ifFull(){
            return rear == maxSize -1;
        }
    
        /**
         * 判断队列是否为空
         * @return
         */
        public boolean isEmpty(){
            return rear == front;
        }
    
        /**
         * 向队列中添加数据
         * @param a
         */
        public void addQueue(int a){
            if(ifFull()){
                throw new RuntimeException("队列已满,无法添加数据");
            }
            rear++;
            this.arr[rear] = a;
        }
    
        /**
         * 从队列中取出一个数据
         */
        public int getQueue(){
            if(isEmpty()){
                throw new RuntimeException("队列为空,无法取出数据");
            }
            front ++;
            return this.arr[front];
        }
    
        /**
         * 展示队列数据
         */
        public void showQueue(){
            if(isEmpty()){
                System.out.println("队列为空");
                return ;
            }
            for (int i = 0; i < this.arr.length; i++) {
                System.out.printf("arr[%d] = %d 
    ",i,arr[i]);
            }
        }
    
        /**
         * 查看队列头
         * @return
         */
        public int headQueue(){
            if(isEmpty()){
                throw new RuntimeException("队列为空");
            }
            return this.arr[front+1];
        }
    
    
    }
    
    

    问题分析并优化

    1. 目前数组使用一次就不能用, 没有达到复用的效果
    2. 将这个数组使用算法,改进成一个环形的队列 取模:%

    数组模拟环形队列

    对前面的数组模拟队列的优化,充分利用数组. 因此将数组看做是一个环形的。(通过取模的方式来实现即可)

    分析说明:

    1)尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的
    时候需要注意 (rear + 1) % maxSize == front 满]

    2)rear == front [空]

    使用数组模拟唤醒队列的思路分析

    package com.doubledumbao.sparsearray.queue;
    
    import java.util.Scanner;
    
    public class CircleArrayQueueDemo {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            char key = ' ';//接收用户输入
            CircleArrayQueue arrayQueue = new CircleArrayQueue(4);
            boolean loop = true;
            while (loop) {
                System.out.println("a(add):添加数据到队列");
                System.out.println("s(show):显示队列");
                System.out.println("e(exit):退出程序");
                System.out.println("g(get):从队列取出数据");
                System.out.println("h(head):查看队列头的数据");
                key = scanner.next().charAt(0);//接收一个字符
                switch (key) {
                    case 'a':
                        System.out.println("输入一个数:");
                        int val = scanner.nextInt();
                        try {
                            arrayQueue.addQueue(val);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                        }
                        break;
                    case 's':
                        arrayQueue.showQueue();
                        break;
                    case 'g':
                        try {
                            System.out.println(arrayQueue.getQueue());
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                        }
                        break;
                    case 'h':
                        try {
                            System.out.println(arrayQueue.headQueue());
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                        }
                        break;
                    case 'e':
                        loop = false;
                        scanner.close();
                        break;
                    default:
                        break;
    
                }
    
            }
    
        }
    }
    
    /**
     * 数组模拟环形队列
     */
    class CircleArrayQueue {
        //队列容量
        private int maxSize;
        //队列前端的下标
        private int front;
        //队列后端的下标+1
        private int rear;
        //存储数据
        private int[] arr;
    
        public CircleArrayQueue(int maxSize) {
            this.maxSize = maxSize;
            this.arr = new int[maxSize];
        }
    
        /**
         * 判断队列是否满了
         *
         * @return
         */
        public boolean ifFull() {
            return front == (rear + 1) % maxSize;
        }
    
        /**
         * 判断队列是否为空
         *
         * @return
         */
        public boolean isEmpty() {
            return rear == front;
        }
    
        /**
         * 向队列中添加数据
         *
         * @param a
         */
        public void addQueue(int a) {
            if (ifFull()) {
                throw new RuntimeException("队列已满,无法添加数据");
            }
            //直接将数据加入
            this.arr[rear] = a;
            //将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 i = front; i < front+size(); i++) {
                System.out.printf("arr[%d] = %d 
    ", i%maxSize, arr[i%maxSize]);
            }
        }
    
        /**
         * 查看队列头
         *
         * @return
         */
        public int headQueue() {
            if (isEmpty()) {
                throw new RuntimeException("队列为空");
            }
            return this.arr[front];
        }
    
        /**
         * 获取队列真实容量
         * @return
         */
        public int size(){
            return (rear+maxSize-front)%maxSize;
        }
    }
    
    
  • 相关阅读:
    字符串替换
    Problem E: Automatic Editing
    正则表达式学习(1)
    python中的enumerate使用
    使用bottle进行web开发(9):文件上传;json传递
    使用bottle进行web开发(8):get的参数传递,form里的额数据传递等
    dict的setdefault(学习bottle源代码)
    使用bottle进行web开发(6):Response 对象
    使用bottle进行web开发(5):Generating Content
    使用bottle进行web开发(4):HTTPError
  • 原文地址:https://www.cnblogs.com/zhaoran8775/p/12789531.html
Copyright © 2011-2022 走看看