数据结构之队列

什么是队列

队列(queue)是一种线性数据结构。与同为线性数据结构的栈不同的是队列中的元素遵循的是先进先出(First In First Out)的规则,和在现实中排队一样,讲究的是先来后到的原则。队列出口端叫做队头(front),队列的入口端叫做队尾(rear)。

与栈类似,队列这种线性数据结构既可以用数组来实现,也可以用链表来实现。用数组来实现时,我们可以自行规定队尾的位置,比如说规定最后一个元素的下一个位置为队尾,或者规定最后一个元素所在的位置为队尾,这两种都行,毕竟是自己实现的。本文规定最后一个元素的下一个位置为队尾。同时,本文采用数组来实现队列。

队列的链表实现如下:

队列的数组实现如下:

 我们使用元素 0 来进行占位。

队列的基本操作

队列的基本操作包括入队(enqueue)和出队(dequeue)两种。

1.入队

入队就是把新元素放入到队列中,只允许从队尾方向入队,入队之后,新元素的下一个元素所在的位置称为队尾。例如:一个已有元素3、5、1、4、9、6的队列,现需要将元素 7 进行入队,那么入队之后的新队列为:

2.出队

出队就是把元素从队头方向移出队列,只允许在队头一侧进行出队操作。出队之后,出队元素的新一个元素作为新的队头。例如:现有一个元素为3、5、1、4、9、6、7的队列,需要将队头元素 3 进行出队操作,那么出队之后新队列即为:

 很显然,队列的出队操作我们只是将队头元素的指向进行了移动,并没有将原有的队头元素进行删除,那这样的话就会导致出现一个问题,不删除原有元素,一直进行出队操作,导致队头左边的空间失去意义,如果不进行数组扩容的话,队列容量只会越来越小的。针对这种情况,便出现了一种特殊的队列——循环队列。

假设现有一个容量为 9 的队列,在经过一系列入队和出队操作之后只剩下了两个元素,这两个元素位于该队列的倒数第一和倒数第二的位置,即该队列已满,但此时有一个新元素需要入队,在不对数组进行扩容的前提下,我们可以让新的队尾指向该数组的首位,利用一下队列中已出队元素的空间。这样一来,整个队列的元素就循环起来了。在物理存储上,队尾的位置也可以在队头之前。当有新元素再次入队时,将其放入数组的首位,队尾继续后移即可。

 那么什么时候我们称该队列已满呢?按照我们的规定,队尾为最后一个元素所在的位置,即(队尾下标 + 1)% 数组长度 = 队头下标时,代表此队列已满,无法再进行入队操作。.因为队尾永远指向最后一个元素的下一个位置,所以队列的最大容量等于数组长度减1。如下所示便是队列已满的情况:

相关代码如下:

package structure.queue;

/**
 * @ClassName: Queue
 * @Author: jiaomubai
 * @Date: 2022/1/30 14:59
 * @Description:
 */
public class Queue {

    private int[] dataArray;
    private int front;
    private int rear;

    public Queue(int capacity) {
        this.dataArray = new int[capacity];
    }

    public void enQueue(int element) {
        if ((rear + 1) % dataArray.length == front) {
            System.out.println("队已满");
            System.out.println();
            return;
        }
        dataArray[rear] = element;
        rear = (rear + 1) % dataArray.length;
        System.out.println("入队后队头元素为:" + dataArray[front]);
        System.out.println("入队后队尾元素为:" + element);
        System.out.println();
    }

    public int deQueue() {
        if (rear == front) {
            System.out.println("队已空");
            System.out.println();
        }
        int deQueueElement = dataArray[front];
        front = (front + 1) % dataArray.length;
        System.out.println("出队后队头元素为:" + dataArray[front]);
        System.out.println("出队后队尾元素为:" + dataArray[rear - 1]);
        System.out.println();
        return deQueueElement;
    }

    public void print() {
        for (int i = front; i != rear - 1; i = (i + 1) % dataArray.length) {
            System.out.print(dataArray[i] + " --> ");
        }
        System.out.println(dataArray[rear - 1]);
        System.out.println();
    }

    public static void main(String[] args) {
        Queue queue = new Queue(6);
        queue.enQueue(1);
        queue.enQueue(2);
        queue.enQueue(3);
        queue.enQueue(4);
        queue.enQueue(5);
        queue.enQueue(6);
        queue.print();
        queue.deQueue();
        queue.deQueue();
        queue.deQueue();
        queue.print();
        queue.enQueue(6);
        queue.enQueue(7);
        queue.print();
    }

}

 上述代码执行结果为:

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值