栈
-
栈是只允许在有序的线性数据集合的一端进行加入和移除数据的线性表。 数据时
后进先出
-
队列是允许在有序的线性数据集合的两端进行加入和移除数据的线性表,数据时
先进先出( FIFO,First In, First Out)
。
栈的常见应用场景
-
实现浏览器的回退和前进功能,需要两个栈
-
检查括号是否成对出现,
思想:从左往右依次扫描,“(” 进,“)” 取栈顶元素进行判断 -
反转字符串:将字符串中的每个字符先入栈再出栈就可以了。
-
维护函数调用:最后一个被调用的函数必须先完成执行,符合栈的
后进先出
特性。
队列
队列最大的特点就是先进先出
,主要的两个操作是入队和出队
。跟栈一样,它既可以用数组来实现,也可以用链表来实现。
用数组实现的叫顺序队列
用链表实现的叫链式队列
长得像一个环的叫循环队列
循环队列
循环队列定义:队列的首位相连形成一个环形的数据结构。定义两个指针front和tail分别指向队列的头和尾
循环队列各个参数的含义:
(1)队列初始化时,front和rear值都为零;
(2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置;
(3)当队列为空时,front与rear的值相等,但不一定为零;
循环队列入队的伪算法
把值存在rear所在的位置;
rear=(rear+1)%maxsize ,其中maxsize代表数组的长度;
循环队列出队的伪算法
先保存出队的值;
front=(front+1)%maxsize ,其中maxsize代表数组的长度;
队空和队满的判定条件:
- 队列为空的判断条件:
head == tail
- 当队满时:
(tail+1)%n=head
如下所示为满时
当队列满时,图中的 tail 指向的位置实际上是没有存储数据的。所以,循环队列会浪费一个位置的存储空间。
队列常见应用场景
-
阻塞队列
当队列为空的时候,出队操作阻塞,当队列满的时候,入队操作阻塞。使用阻塞队列我们可以很容易实现“生产者 - 消费者“模型
-
线程池中的请求/任务队列
线程池中没有空闲线程时,新的任务请求线程资源时,线程池会将这些请求放在队列中,当有空闲线程的时候,会从队列中获取任务交给空闲线程执行
分为两种实现方式:- 基于链表的实现方式,可以实现一个支持无限排队的
无界队列
, - 而基于数组实现的
有界队列
,队列的大小有限
- 基于链表的实现方式,可以实现一个支持无限排队的
-
数据库连接池等待队列
-
Linux 内核进程等待队列
-
消息队列