• 队列


    队列的介绍

    • 队列是一个有序列表,可以用数组或是链表来实现
    • 遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的数据要后取
    • 示意图:(使用数组模拟队列示意图)

    数组模拟队列思路

    • 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中,maxSize是该队列的最大容量.
    • 因为队列的输出,输入是分别从前后端来处理,因此需要两个变量front和rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变,如下图所示:
    • 当我们将数据存入队列是称为"addQueue",addQueue的处理需要有两个步骤:思路分析
      • 将尾指针往后移:rear+1,当front==rear 时为空 注意,这里的front和rear初始值都是-1
      • 若尾指针rear小于队列的最大下标 maxSize-1,则可以将数据存入队列中,否则无法存入数据. rear == maxSize-1 队满

    代码实现

    public class arrayQueue {
        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("p(push):添加数据到队列");
                System.out.println("g(get):从队列中取出数据");
                System.out.println("h(head):查看队列头数据");
                key = scanner.next().charAt(0); //接受一个字符
                switch (key){
                    case 's':
                        queue.showQueue();
                        break;
                    case 'e':
                        scanner.close();
                        loop = false;
                        break;
                    case 'p':
                        System.out.println("请输入一个数:");
                        int val = scanner.nextInt();
                        queue.push(val);
                        break;
                    case 'g':
                       try {
                           int res = queue.pop();
                           System.out.println("取出的数据为:"+res);
                       }catch (Exception e){
                           System.out.println(e.getMessage());
                       }
                       break;
                    case 'h':
                        try {
                            int res = queue.headQueue();
                            System.out.println("取出的数据为:"+res);
                        }catch (Exception e){
                            System.out.println(e.getMessage());
                        }
                    default:
                        break;
                }
            }
        }
    }
    //使用数组模拟一个队列
    class ArrayQueue{
        private int maxSize; //表示数组的最大容量
        private int front;//队头
        private int rear;//队尾
        private int[] arr;//该数据用于存放数据,模拟队列
    
        //创建队列的构造器
        public ArrayQueue(int size){
            this.maxSize = size;
            this.front = -1;
            this.rear = -1;
            this.arr = new int[maxSize];
        }
        //判断队列是否满
        public boolean isFull(){
            return rear == maxSize-1;
        }
        //判断队列是否为空
        public boolean isEmpty(){
            return front == rear;
        }
        //添加数据到队列
        public void push(int num){
            //添加之前,先判断是否为满
            if (isFull()){
                System.out.println("队列满,不能添加数据!!");
                return;
            }
            rear++;
            arr[rear] = num;
        }
        //获取队列元素,出队列
        public int pop(){
            //出队之前,先判断是否为空
            if (isEmpty()){
                throw new RuntimeException("队列为空,不能出队!!");
            }
            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]);
            }
        }
    
        //显示队列的头数据
        public int headQueue(){
            if (isEmpty()){
                throw new RuntimeException("队列为空,没有数据!!");
            }
            return arr[front+1];  //这里不是出队,不能修改front的值
        }
    }
    

    问题分析并优化

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

    数组模拟环形队列

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

    • 分析说明:
      • 尾索引(rear)的下一个为头索引(front)时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意(rear+1)%maxSize == front 满
      • rear == front 空
    • 思路如下:
      • front变量的含义做一个调整:front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值=0.
      • rear变量的含义做一个调整:rear指向队列最后一个元素的后一个位置,因为希望空出一个空间.rear的初始值=0
      • 当队列满时,条件是(rear+1)%maxSize == front
      • 当队列为空的条件是:rear == front
      • 队列中的有效数据个数是:(rear-front + maxSize)%maxSize

    代码实现

    public class circleArrayQueue {
        public static void main(String[] args) {
            CircleQueue queue = new CircleQueue(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("p(push):添加数据到队列");
                System.out.println("g(get):从队列中取出数据");
                System.out.println("h(head):查看队列头数据");
                key = scanner.next().charAt(0); //接受一个字符
                switch (key) {
                    case 's':
                        queue.showQueue();
                        break;
                    case 'e':
                        scanner.close();
                        loop = false;
                        break;
                    case 'p':
                        System.out.println("请输入一个数:");
                        int val = scanner.nextInt();
                        queue.push(val);
                        break;
                    case 'g':
                        try {
                            int res = queue.pop();
                            System.out.println("取出的数据为:" + res);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                        break;
                    case 'h':
                        try {
                            int res = queue.head();
                            System.out.println("取出的数据为:" + res);
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                    default:
                        break;
                }
            }
        }
    }
    
    class CircleQueue {
        private int maxSize;
        private int front;
        private int rear;
        private int[] arr;
    
        //创建队列的构造器
        public CircleQueue(int maxSize) {
            this.maxSize = maxSize;
            arr = new int[maxSize];
            front = 0;
            rear = 0;
        }
    
        //判断队列是否满
        public boolean isFull() {
            return (rear + 1) % maxSize == front;
        }
    
        //判断队列是否为空
        public boolean isEmpty() {
            return rear == front;
        }
    
        //添加数据到队列
        public void push(int num) {
            if (isFull()) {
                System.out.println("队列满了,不能添加数据!!");
                return;
            }
            arr[rear] = num;
            rear = (rear + 1) % maxSize;
        }
    
        //获取队列元素,出队列
        public int pop() {
            if (isEmpty()) {
                throw new RuntimeException("队列为空,不能出队!!");
            }
            int tmp = arr[front];
            front = (front + 1) % maxSize;
            return tmp;
        }
    
        //显示队列的所有数据
        public void showQueue() {
            if (isEmpty()) {
                System.out.println("队列为空,不能显示!!");
                return;
            }
            for (int i = front; i < front + size(); i++) {
                System.out.printf("arr[%d] = %d
    ", i % maxSize, arr[i % maxSize]);
            }
        }
    
        //获取队列中有效的数据个数
        public int size() {
            return (rear - front + maxSize) % maxSize;
        }
    
        //显示队列的头数据
        public int head() {
            if (isEmpty()) {
                throw new RuntimeException("队列为空,不能显示!!");
            }
            return arr[front];
        }
    
    }
    
    
  • 相关阅读:
    转:CRF++
    ProBase
    图形数据库 Neo4j 开发实战
    Linux 下升级python和安装pip
    TensorFlow (RNN)深度学习 双向LSTM(BiLSTM)+CRF 实现 sequence labeling 序列标注问题 源码下载
    开源项目kcws代码分析--基于深度学习的分词技术
    文本情感分类(二):深度学习模型
    文本情感分类(一):传统模型
    重要博文
    LSTM 文本情感分析/序列分类 Keras
  • 原文地址:https://www.cnblogs.com/liuzhidao/p/13791762.html
Copyright © 2020-2023  润新知