zoukankan      html  css  js  c++  java
  • 数据结构和算法003——队列(一般数组&&环形数组)

    1、用数组模拟队列

    先入先出FIFO

    import java.util.Scanner;
    
    /**
     * @author yk
     * @create 2020/11/8 18:38
     * 用数组模拟队列
     * @description
     */
    public class Test004 {
    
        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 value = scanner.nextInt();
                        queue.addQueue(value);
                        break;
                    case 'g':
                        try {
                            int res = queue.getQueue();
                            System.out.printf("取出的数是%d
    ",res);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                        break;
                    case 'h':
                        try {
                            int res = queue.peekQueue();
                            System.out.printf("队列头的数是%d
    ",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;
    
        /**
         * 创建队列的构造器
         * @param arrMaxSize
         */
        public ArrayQueue(int arrMaxSize){
            maxSize = arrMaxSize;
            arr = new int[maxSize];
            //指向队列头部前面一个位置
            front = -1;
            //指向队列尾部(即就是队列最后一个数据)
            rear = -1;
        }
    
        /**
         * 判断队列是否满
         * @return
         */
        public boolean isFull(){
            return rear == maxSize - 1;
        }
    
        /**
         * 判断队列是否为空
         * @return
         */
        public boolean isEmpty(){
            return rear == front;
        }
    
        /**
         * 添加数据到队列
         * @param n
         */
        public void addQueue(int n){
            if (isFull()) {
                System.out.println("队列满,不能加入数据!");
                return;
            }
    
            //让rear后移
            rear++;
            arr[rear] = n;
        }
    
        /**
         * 获取队列数据(出队列),一个一个取
         * @return
         */
        public int getQueue(){
            if (isEmpty()){
                System.out.println("队列为空");
                //通过抛出异常来处理
                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
    ",i,arr[i]);
            }
        }
    
        /**
         * 获取队列头的数据
         * @return
         */
        public int peekQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列为空,不能取数据");
            }
            return arr[front + 1];
        }
    }

    2、环形队列

    以上代码有个问题,数组只能使用一次,当队列满了后,一直调用getQueue()方法直到队列中没数据时,数据也加不进去了。

    解决办法:将这个数组使用算法,改进成环形队列。

    思路如下:

    1. front初始值为0;
    2. front变量含义做一个调整:front就指向队列的第一个元素,也就是arr[front]就是队列的第一个元素;
    3. rear变量含义做一个调整:rear就指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定。
    4. 当队列满时,条件是(rear+1)%maxSize = front(理解下:如下图)
    5. 当队列为空时,rear = front
    6. 队列中有效数据的个数为:(rear + maxSize - front) % maxSize    
    rear front maxSize 有几个值
    1 0 3 1

       7.改写代码

    下图是满的时候,红表示front的指针,蓝表示rear的指针

    下面表示队列为空时。

     

    import java.util.Scanner;
    
    /**
     * @author yk
     * @create 2020/11/8 20:25
     * 环形队列
     * @description
     */
    public class Test5 {
    
        public static void main(String[] args) {
            //测试
            //创建一个队列    设置4,其队列的有效数据最大是3
            CircleQueue queue = new CircleQueue(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':
                        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.printf("取出的数是%d
    ",res);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                        break;
                    case 'h':
                        try {
                            int res = queue.peekQueue();
                            System.out.printf("队列头的数是%d
    ",res);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                        break;
                    case 'e':
                        scanner.close();
                        loop = false;
                        break;
                    default:
                        break;
                }
            }
            System.out.println("程序退出");
        }
    }
    
    class CircleQueue {
        //表示数组的最大容量
        private int maxSize;
    
        //front变量含义做一个调整:front就指向队列的第一个元素,也就是arr[front]就是队列的第一个元素;默认0
        private int front;
    
        //rear变量含义做一个调整:rear就指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定。默认0
        private int rear;
    
        //该数组用于存放数据,模拟队列
        private int[] arr;
    
        /**
         * 创建队列的构造器
         * @param arrMaxSize
         */
        public CircleQueue(int arrMaxSize){
            maxSize = arrMaxSize;
            arr = new int[maxSize];
        }
    
        /**
         * 判断队列是否满
         * @return
         */
        public boolean isFull(){
            return (rear + 1) % maxSize == front;
        }
    
        /**
         * 判断队列是否为空
         * @return
         */
        public boolean isEmpty(){
            return rear == front;
        }
    
        /**
         * 添加数据到队列
         * @param n
         */
        public void addQueue(int n){
            if (isFull()) {
                System.out.println("队列满,不能加入数据!");
                return;
            }
    
            //将数据放入,rear指针所在就是数据需要插入的地方
            arr[rear] = n;
            //rear后移一位,这里需要考虑取模(在这里预留了一位空空间)
            rear = (rear + 1) % maxSize;
        }
    
        /**
         * 获取队列数据(出队列),一个一个取
         * @return
         */
        public int getQueue(){
            if (isEmpty()){
                System.out.println("队列为空");
                //通过抛出异常来处理
                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 < size(); i++) {
                System.out.printf("arr[%d]=%d
    ",i % maxSize,arr[i % maxSize]);
            }
        }
    
        /**
         * 求出当前队列有效数据个数
         * @return
         */
        public int size(){
            return (rear + maxSize - front) % maxSize;
        }
    
        /**
         * 获取队列头的数据
         * @return
         */
        public int peekQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列为空,不能取数据");
            }
            return arr[front];
        }
    }
  • 相关阅读:
    我(webabcd)的文章索引
    学习重构的一些思考
    学习重构的一些思考
    软件编程思想读后感
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/su-ke/p/13945930.html
Copyright © 2011-2022 走看看