【数据结构与算法】之队列的基本介绍及其数组、链表实现---第五篇

本文详细介绍了队列的基本概念,包括定义、队列与栈的区别,以及队列的数组和链表实现。重点讨论了数组实现队列时面临的问题和解决方法,提出了循环队列的概念,以解决数据搬移问题。此外,还探讨了阻塞队列和并发队列在多线程环境中的应用和重要性。
摘要由CSDN通过智能技术生成

博主秋招提前批已拿百度、字节跳动、拼多多、顺丰等公司的offer,可加微信:pcwl_Java 一起交流秋招面试经验,可获得博主的秋招简历和复习笔记。 

一、队列的基本概念

1、定义

队列是一种先进先出的线性表。它只允许在表的前端进行删除操作,而在表的后端进行插入操作,具有先进先出、后进后出的特点。进行插入操作的一端成为队尾(tail),进行删除操作的一端称为队头(head)。当队列中没有元素时,则称之为空队列。

在队列中插入一个元素称为入队,从队列中删除一个元素称为出队。因为队列只允许在队尾插入元素,在队头删除元素,所以队列又称为先进先出(FIFO-first  in  first  out)线性表。其实队列这种数据结构的特性,让我们很容易就想到了平时生活中我们排队场景,真是无处不在啊。。。图书馆、食堂、餐厅、公交车。。。

而在程序框架方面也有很多应用:最常见的就是各种“池“,比如:线程池、数据库连接池,分布式中的消息队列等待。都体现出一种公平的思想,即先到的先得。


2、队列和栈

其实队列和栈有很多相似的地方,栈的两个基本操作:压栈(push)和弹栈(pop),而队列的最基本的两个操作是:入队(enqueue())和出队(dequeue())。因此队列和栈一样,也是一种操作受限的数据结构。


3、队列的入队和出队操作(以数组为例)

入队操作enqueue:每次从队尾插入元素,时间复杂度:O(1)

出队操作dequeue:每次从队头删除元素,时间复杂度:O(n)

但是可以发现,数组实现的队列有很大的不足,每次从数组头部删除元素后,需要将头部的所有元素往队首移动一个位置,这是一个时间复杂度为O(n)的操作。

你可能会想到一种办法:每进行一次出队操作,就将队首的的标志往队尾移动一个内存空间,这样就不用进行数据搬移了,但是很明显这样又会产生一个很大的弊端,当队尾标志tail移动到最右边时,即使数组中还有空闲的内存空间,也无法往队列中添加数据了,不能很好的利用内存空间。

你可能还会想到一种办法:和JVM垃圾回收类似的思想,在出队操作的时候,我们不用先搬移数据,当没有空间空间,无法插入新数据的时候,在进行一次整体的数据搬移操作,这样可以将出队操作的时间复杂度降低为O(1),但是入队操作时,需要先判断队列中是否有空间的内存空间,如果有,直接入队,但是如果没有,则需要将队列中的数据进行一次整体的搬移,这样时间复杂度就为O(n)了,显然也不理想。其实现代码见文末:动态队列的数组实现

循环队列很好的解决了这个问题。见下文......


4、循环队列

从上面的数组实现的队列来看,其删除操作的时间复杂度为O(n),而我们希望得到时间复杂度都为O(1)的插入和删除操作,所以循环队列就很好的符合了我们的标准。

所谓的循环队列,就是长的像一个环,原本的队列是由头有尾的,是一条直线,我们现在将首位相连,就形成了一个环。如下图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值