zoukankan      html  css  js  c++  java
  • Java数据结构(三)—— 队列

    队列(Queue)

    队列的应用场景

    银行排队案例,买票案例

    队列概述

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

    • 遵循先进先出的元组

    队列的实现方式

    数组形式

    image-20201016083130818

    image-20201016083429638

    代码实现

    package com.why.data_structure.queue;

    import java.awt.*;
    import java.util.Arrays;
    import java.util.Scanner;

    /**
    * @Description TODO 用数组模拟队列
    * @Author why
    * @Date 2020/10/16 8:40
    * Version 1.0
    **/
    public class ArrayQueueDemo {
       public static void main(String[] args) {
           ArrayQueue arrayQueue = new ArrayQueue(20);
           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.println("输入一个数");
                       int value = scanner.nextInt();
                       arrayQueue.addQueue(value);
                       break;
                   case 'g':
                       try {
                           int res = arrayQueue.subQueue();
                           System.out.printf("取出的数据是%d ",res);
                      }catch (Exception e){
                           System.out.println(e.getMessage());
                      }
                       break;
                   case 'h':
                       try {
                           int res = arrayQueue.headQueue();
                           System.out.printf("数据头数据是%d ",res);
                      }catch (Exception e){
                           System.out.println(e.getMessage());
                      }
                       break;
                   case 'e':
                       scanner.close();
                       loop = false;
                       System.out.println("程序退出");
                       break;
                   default:
                       break;

              }
          }
      }
    }

    //编写一个数组模拟队列的类
    class ArrayQueue{
       private int maxSize;//数组最大容量
       private int front;//队列头
       private int rear;//队列尾部
       private int[] arr;//存放数据,模拟队列

       /**
        * 队列初始化,构造队列
        * @param maxSize
        */
       public ArrayQueue(int maxSize) {
           this.maxSize = maxSize;
           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+=1;//rear后移
           arr[rear] = n;
      }

       /**
        * 出队获得队列的值
        * @return
        */
       public int subQueue(){
           //判空
           if (isEmpty()){
               throw new RuntimeException("队列为空!");
          }
           return arr[front+=1];
      }

       /**
        * 显示队列所有数据
        */
       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 headQueue(){
           if (isEmpty()){
               throw new RuntimeException("队列空");
          }
           return arr[front+1];
      }
       public ArrayQueue() {
      }

       public int getMaxSize() {
           return maxSize;
      }

       public void setMaxSize(int maxSize) {
           this.maxSize = maxSize;
      }

       public int getFront() {
           return front;
      }

       public void setFront(int front) {
           this.front = front;
      }

       public int getRear() {
           return rear;
      }

       public void setRear(int rear) {
           this.rear = rear;
      }

       public int[] getArr() {
           return arr;
      }

       public void setArr(int[] arr) {
           this.arr = arr;
      }

       @Override
       public String toString() {
           return "ArrayQueue{" +
                   "maxSize=" + maxSize +
                   ", front=" + front +
                   ", rear=" + rear +
                   ", arr=" + Arrays.toString(arr) +
                   '}';
      }
    }

    问题分析

    • 目前数组使用一次就不能使用,达不到复用的效果

    • 使用算法,改进成环形队列

    数组模拟环形队列

    思路如下
    1. front变量含义做调整,front指向数组队列的第一个元素,也就是说arr[front]是队列的第一个元素

    2. rear变量含义做调整,rear指向队列的最后一个元素的后一个位置,希望空出一个空间作为一个约定

    3. 初始化 front = 0;rear = 0;

    4. 当队列满时,条件是(rear+1)% maxSize == front(满)

    5. 当队列为空时,条件是rear == front(空)

    6. 队列中有效的数据个数为:(rear+maxSize-front)% maxSize

    环形队列代码实现

    package com.why.data_structure.queue;

    import java.util.Scanner;
    import java.util.concurrent.CountDownLatch;

    /**
    * @Description TODO 环形队列实现与测试
    * @Author why
    * @Date 2020/10/16 11:01
    * Version 1.0
    **/
    public class RingQueueDemo {
       public static void main(String[] args) {

           //设置5有效数据最大为4,有一个预留空间
           RingQueue ringQueue = new RingQueue(5);
           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':
                       ringQueue.getAll();
                       break;
                   case 'a':
                       System.out.println("输入一个数");
                       int value = scanner.nextInt();
                       ringQueue.addQueue(value);
                       break;
                   case 'g':
                       try {
                           int res = ringQueue.subQueue();
                           System.out.printf("取出的数据是%d ", res);
                      } catch (Exception e) {
                           System.out.println(e.getMessage());
                      }
                       break;
                   case 'h':
                       try {
                           int res = ringQueue.headQueue();
                           System.out.printf("数据头数据是%d ", res);
                      } catch (Exception e) {
                           System.out.println(e.getMessage());
                      }
                       break;
                   case 'e':
                       scanner.close();
                       loop = false;
                       System.out.println("程序退出");
                       break;
                   default:
                       break;
              }
          }
      }
    }

    class RingQueue{
       private int front;//头指针
       private int  rear;//尾指针
       private int[] arrayArr;//存放数据的数组
       private int maxSize;//最大容量

       /**
        * 初始化设置最大容量,将front = 0; rear = 0
        * @param maxSize
        */
       public RingQueue(int maxSize) {
           this.maxSize = maxSize;
           front = 0;
           rear = 0;
           arrayArr = new int[maxSize];
      }

       /**
        * 判满
        */
       public boolean isFull(){
           return (rear +1) % maxSize == front;
      }

       /**
        * 判空
        */
       public boolean isEmpty(){
           return rear == front;
      }

       /**
        * 入队,添加数据
        * @param n
        */
       public void addQueue(int n){
           if (isFull()){
               System.out.println("队列已满,不可添加数据");
               return;
          }
           arrayArr[rear] = n;
           rear = (rear+1) % maxSize;
      }

       /**
        * 出队
        * @return
        */
       public int subQueue(){
           if (isEmpty()){
               throw new RuntimeException("队列为空,无数据可取");
          }
           int value = arrayArr[front];
           front = (front+1)%maxSize;
           return value;
      }

       /**
        * 输出所有数据
        */
       public void getAll(){
           //遍历
           if (isEmpty()){
               System.out.println("队列空");
               return;
          }
           //思路
           //从front开始遍历遍历(rear+maxSize-front)% maxSize个元素
           for (int i = front; i <front+size(); i++) {
               System.out.printf("arr[%d]=%d ",i%maxSize,arrayArr[i%maxSize]);
          }
      }

       /**
        * 显示头数据
        * @return
        */
       public int headQueue(){
           if (isEmpty()){
               throw new RuntimeException("队列空");
          }
           return arrayArr[front];
      }

       public int size(){
           return (rear+maxSize-front)% maxSize;
      }

       public RingQueue() {
      }
    }

     所有源码都可在gitee仓库中下载:https://gitee.com/vvwhyyy/java_algorithm

  • 相关阅读:
    快学Scala 第6章 对象
    Ch05 类
    Ch04 映射和元组
    Ch03 数组相关操作
    Ch02 控制结构和函数
    Ch01 基础
    28.创建对象两种方式、对象的方法、属性、获取属性值的两种方法、属性名含特殊符号时获取属性值的方法、添加属性及值的方法、删除属性的方法、使用方式、遍历对象属性for(var prop in obj)
    27.函数循环扩展作业、非常重要涉及编程思想(一天看一遍) 编程思想其实就是算法,、感悟、演算
    26 .闭包 、函数表达式在for中无法接受实时改变的变量、 在for里要将函数表达式封装成闭包才能接受实时变化的参数,并要将函数表达式return出去
    25.函数例题-预解析 作用域 、函数变量优先级、全局变量污染(直接在全局声明 、 函数里的变量没声明)但是函数里的变量没声明造成的全局变量污染有个前提,函数要被调用)
  • 原文地址:https://www.cnblogs.com/whystudyjava/p/14043251.html
Copyright © 2011-2022 走看看