春去秋来,岁岁平安|

发着呆看星

园龄:2年9个月粉丝:1关注:0

2023-04-14 09:52阅读: 40评论: 0推荐: 0

队列

引入

  • 什么是队列?
  • 在日常生活中,超市排队结账,就是一个简单的队列
    • 排队,先到先排,排在前面 ,后到后排,排在后面,不能插队
    • 先排的人,先结账,后排的人后结账
  • 所以我们就可以看出 队列的特点
    • 从一端入队,从一端出队
    • **先入队的元素,先离开,后入队的元素,后离开 **
  • 队列是一种只允许在一端进行插入操作,在另一端进行删除操作的先入先出的受限的线性表

队列概念.png

队列的实现思路

  • 和栈一样,队列有两种实现方式
  • 数组实现的 顺序队列
  • 链表实现的 链队列

普通数组队列

数组队列.png

  • 思路
  • 创建一个类,类中有几个属性
    • maxsize:定义了数组的长度
    • front:指向队头元素,从0开始
    • rear:指向队尾元素的后一个位置,从0开始
  • 判断满员
    • 当rear的值 > 数组最大元素下表 ,就代表已经满员了
      • 即可换算为 rear == maxsize 时 ,满员,不能加人
  • 判断是否为空
    • 当 front == rear 时,代表现在没有人 ,不能取出(遍历)数组 ,例如:最初时

数组列队满员情况.png

数组队列为空.png

  • 入队操作
  • 当一个元素入队时,判断是否满员
    • 若满员:则不能添加
    • 若没有满员,则将rear所在的元素下表赋上值,赋完值之后,在rear++
  • 出队操作
    • 当要执行出队操作时,要先判断列队是否为空
      • 为null:则不能出队
      • 不为bull:则front++,即向前移动一位
  • 遍历操作
    • 当要执行遍历操作时,需要判断列队是否为null
      • 为null:代表不能遍历
      • 不为null:代表可以遍历 ,[ front , rear )
  • 数组队列类
public class ArrayQueue {
    private int maxSize;
    private int front;
    private int rear;
    private int[] queue;

    public ArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        queue = new int[maxSize];
        front = 0;
        rear = 0;
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public boolean isFull() {
        return rear == maxSize;
    }

    public void addEl(int n) {
        if (!isFull()) {
            queue[rear] = n;
            rear++;
        } else {
            System.out.println("当前列队已满,不能加入");
        }
    }

    public void removeEl() {
        if (!isEmpty()) {
            front++;
        }else {
            System.out.println("当前队列没有元素,不能移除");
        }
    }

    public void showQueue() {
        if (!isEmpty()) {
            int temp = 0;
            for (int i = front; i < rear; i++) {
                temp++;
                System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
            }
        }else {
            System.out.println("当前队列没有元素");
        }
    }

    public void showFirst(){
        if (!isEmpty()){
            System.out.println("第一个人是:"+queue[front]);
        }else {
            System.out.println("当前队列没有元素");
        }
    }
}
  • 测试方法
ArrayQueue arrayQueue = new ArrayQueue(5);
boolean loop = true;
Scanner scanner = new Scanner(System.in);
while (loop){
    System.out.println("==================================");
    System.out.println("(a):进入队列");
    System.out.println("(r):移除队列");
    System.out.println("(l):队列列表");
    System.out.println("(s):队列首元素");
    System.out.println("(e):退出程序");
    System.out.print("请选择你要的操作:");
    char c = scanner.next().charAt(0);
    switch (c){
        case 'a':
            System.out.print("请输入要入对的编号:");
            Scanner s = new Scanner(System.in);
            int i = s.nextInt();
            arrayQueue.addEl(i);
            break;
        case 'r':
            arrayQueue.removeEl();
            break;
        case 'l':
            arrayQueue.showQueue();
            break;
        case 's':
            arrayQueue.showFirst();
            break;
        case 'e':
            loop = false;
            break;
    }
System.out.println();
}

循环数组队列

  • 数组队列有一个很明显的缺点:数组只能使用一次,不能循环使用
  • 那有没有一种办法能够使数组循环使用呢?这里就需要循环队列
    • 循环队列:可以将数组想象成一个环,

循环数组队列概念.png

  • 思路
  • 该数组中的指针 front 和 rear 有一个特点就是循环
    • 当rear指向7时 ,再添加一个元素 ,元素添加至 7 处 ,rear 在 0 处
    • 如果一直没有出队列 ,那么 front就在 0 处 ,rear == front
    • 按照判定 ,rear == front 时 ,队列为 null ,显然不符合
    • 所以,循环队列永远需要有一个 空闲元素 ,队列的最大长度 = 数组长度 - 1
  • 创建一个类,类中有几个属性
    • maxsize:定义了数组的**可储存的最大长度 **
      • 数组的长度为 :maxsize + 1
    • front:指向队头元素,从0开始
    • rear:指向队尾元素的后一个位置,从0开始
  • 判断是否为空
    • 当 front == rear 时,代表现在没有人 ,不能取出(遍历)数组 ,例如:最初时
  • 判断队列是否已满
    - ( rear + 1 ) % length = front
  • 计算循环列队有效元素长度
    • ( rear + length - front )% length
  • 遍历循环列队算法
    • for (int i = front ; i <front+queueSize() ;i++ ){

** System.out.println("元素下表为"+( i % queue.length)+"的元素的值为"+queue[ i % queue.length]);**

** }**

循环列队满员情况.png

  • 添加操作
  • 判断是否已满
    • 满:return
    • 未满:将值 赋给 现在 rear的坐标
      • rear == maxsize
        • rear = 0
      • rear != 7
        • rear++
  • 删除操作
    • 判断是否为null
      • 为null : return
      • 不为null :
        • front == 7
          • front = 0
        • front != 7
          • front++
  • 遍历操作
    • 判断是否为null
      • 为null :return
      • 不为null
        • rear > front :
          • 直接 [ front , rear)
        • rear < front
          • 1)[ front , 7 ]
          • 2)[0 , rear)
public class LoopArrayQueue {
    private int maxSize;
    private int front;
    private int rear;
    private int[] queue;

    public LoopArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        queue = new int[maxSize+1];
        front = 0;
        rear = 0;
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public boolean isFull() {
        return (( rear + 1 ) % queue.length) == front;
    }

    // 添加操作
    public void addEl(int n) {
        if (!isFull()) {
            queue[rear] = n;
            if (rear == maxSize){
                rear = 0;
            }else {
                rear++;
            }
        } else {
            System.out.println("当前列队已满,不能加入");
        }
    }

    // 删除操作
    public void removeEl() {
        if (!isEmpty()) {
            if (front == maxSize){
                front = 0;
            }else {
                front++;
            }
        }else {
            System.out.println("当前队列没有元素,不能移除");
        }
    }

    // 遍历队列中的所有元素
    public void showQueue() {
        if (!isEmpty()) {
            /*
            普通思维方式遍历
            if (rear > front){
                for (int i = front; i < rear; i++) {
                    System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
                }
            }else {
                for (int i = front; i < queue.length; i++) {
                    System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
                }
                for (int i = 0; i < rear; i++){
                    System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
                }
            }
            */
            // 利用一个小算法,遍历
            System.out.println("当前队列元素个数为:" +queueSize());
            for (int i = front ; i <front+queueSize() ;i++ ){
                System.out.println("元素下表为"+(i%queue.length)+"的元素的值为"+queue[i%queue.length]);
            }
        }else {
            System.out.println("当前队列没有元素");
        }
    }

    // 查看第一个元素
    public void showFirst(){
        if (!isEmpty()){
            System.out.println("第一个人是:"+queue[front]);
        }else {
            System.out.println("当前队列没有元素");
        }
    }

    // 计算队列中元素的个数
    public int queueSize(){
        return (rear+queue.length - front) % queue.length;
    }
}
 public static void main(String[] args) {
    LoopArrayQueue arrayQueue = new LoopArrayQueue(5);
    boolean loop = true;
    Scanner scanner = new Scanner(System.in);
    while (loop){
        System.out.println("==================================11");
        System.out.println("(a):进入队列");
        System.out.println("(r):移除队列");
        System.out.println("(l):队列列表");
        System.out.println("(s):队列首元素");
        System.out.println("(e):退出程序");
        System.out.print("请选择你要的操作:");
        char c = scanner.next().charAt(0);
        switch (c){
            case 'a':
                System.out.print("请输入要入对的编号:");
                Scanner s = new Scanner(System.in);
                int i = s.nextInt();
                arrayQueue.addEl(i);
                break;
            case 'r':
                arrayQueue.removeEl();
                break;
            case 'l':
                arrayQueue.showQueue();
                break;
            case 's':
                arrayQueue.showFirst();
                break;
            case 'e':
                loop = false;
                break;
        }
        System.out.println();
    }
}

本文作者:发着呆看星

本文链接:https://www.cnblogs.com/fzdkx/p/17317365.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   发着呆看星  阅读(40)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起