• 单向队列和环形队列


    一、队列是什么?

    队列queue:一种线性数据结构,队列中的元素只能先入先出(First In First Out,简称FIFO),队列的出口端叫作队头(front),队列的入口端叫作队尾(rear)。

    队列这种数据结构本身是有序列表,既可以用数组来实现,也可以用链表来实现:

      如图:数组实现队列,队尾往往设置在最后一个元素的下一个位置。

    队列的操作一般分为-------------入队和出队

    ---入队:把新元素放入队列中,只允许在队尾的位置放入元素,新元素的下一个位置将会成为新的队尾。

    ---出队:把元素移出队列,只允许在队头一侧移出元素,出队元素的后一个元素将会成为新的队头。

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

    二、单向队列怎么实现?

    思路分析:入队和出队

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

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

    //定义队列的基本组成
    private int maxSize; //表示数组的最大容量
    private int front; //队头指针
    private int rear; //队尾指针
    private int[] arr;
    //创建队列构造器
    public ArrayQueue(int arrMaxSize) {
      this.maxSize = arrMaxSize;
      this.front = -1; //指向队列头部的之前的位置,没有任何数据时,指向虚无
      this.rear = -1; //指向队列尾部的位置,最后一个元素的位置
      this.arr = new int[this.maxSize];
    }
    //判断队列是否满了
    public boolean isFull() {
      //(rear+1)%array.length == front)
      return rear == maxSize;
    }
    //判断队列是否为空
    public boolean isEmpty() {
      return rear == front;
    }
    //添加数据到队列
    public void addQueue(int element) {
      if(isFull()) {
      System.out.println("队列已满");
      return ;
      }
      rear++;
      arr[rear] = element;
    }
    //获取队列值,出队列
    public int getQueue() {
      //判断是否为空
      if(isEmpty()) {
      throw new RuntimeException("队列为空");
      }
      front++;

           int value = arr[front];
           return value;

    }
    //显示队列的所有数据
    public void showQueue() {
      //遍历
      if(isEmpty()) {
      System.out.println("队列为空,遍历个锤子");
    }
    for(int i=0; i < arr.length; i++) {
      System.out.printf("arr[%d]=%d ",i,arr[i]);
      }
    }
    //实现队列头部
    public int headQueue() {
      if(isEmpty()) {
      System.out.println("队列为空,没有头");
      }
      return arr[front+1];
    }

    缺陷:数组无法复用,造成空间浪费。

    三、环形队列怎么实现?

    //注意环形队列最大实际有效值为 最大值-1,因为需要空余一个数组位,用于作变动,让数组尾指针重新指回数组的首位(取模之法)

    //定义队列的基本机构

    private int maxSize;   //表示数组的最大容量

    private int front;    //队头指针,队列的第一个元素,初始值为0

    private int rear;     //队尾指针,队列最后一个元素的后一个位置,初始值为0

    private int[] arr;

    //创建队列构造器

    public CirQueue(int arrMaxSize) {

      this.maxSize = arrMaxSize;

      this.arr = new int[this.maxSize];

    }

    //判断队列是否满了

    public boolean isFull() {

      //(rear+1)%array.length == front)

      return (rear+1)%maxSize == front;

    }

    //判断队列是否为空

    public boolean isEmpty() {

      return rear == front;

    }

    //添加数据到队列

    public void addQueue(int element) {

      if(isFull()) {

      System.out.println("队列已满");

      return ;

      }

      //将元素加入队列

      arr[rear] = element;

      //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;

      }

      

          //输出---队列---遍历
          //从哪里开始遍历,到哪里结束呢?----头指针在哪,就从那个开始
          //得到环形数组中具有多少个元素。-----当前队列的有效元素具体--(rear + maxSize - front) % maxSize
          //从头指针 开始

      for(int i=front; i < front+size(); i++) {

      System.out.printf("arr[%d]=%d ",i % maxSize,arr[i % maxSize ]);

      }

    }

    //求出当前队列有效数据的个数

    public int size() {

      return (rear + maxSize - front) % maxSize;

    }

    //实现队列头部

    public int headQueue() {

      if(isEmpty()) {

      System.out.println("队列为空,没有头");

      }

      return arr[front+1];

    }

    
    

     方法二:

    private int[] array;
    private
    int front;
    private int rear;
    //环形队列构造器
    public MyQueue(int capacity){
      
    this.array = new int[capacity];
    }
    //入队
    public void enQueue(int element) throws Exception {
      if((rear+1)%array.length == front){
          throw new Exception(" 队列已满!");
       }
        array[rear] = element;
        rear =(rear+1)%array.length; }
    //出队
    public int deQueue() throws Exception {
      if(rear == front){
        throw new Exception(" 队列已空!");
    }
      int deQueueElement = array[front];
      front =(front+1)%array.length;
      return deQueueElement;
    }
    //输出---队列---遍历
    public void output(){
    for(int i=front; i!=rear; i=(i+1)%array.length){
       System.out.println(array[i]);
      }
    }
    //此法来源于---漫画算法:小灰的算法之旅 
  • 相关阅读:
    C# 保存base64格式图片
    C# 日期比较
    Socket的使用
    地质演变完整事记
    计算机实用的使用技巧
    ebook 电子书项目
    ppt演讲者模式
    IT行业三大定律
    史前生命
    Oracle DataGuard发生归档丢失增量备份恢复备库
  • 原文地址:https://www.cnblogs.com/Tanggula-pioneer/p/11823021.html
Copyright © 2020-2023  润新知