数据结构
栈
栈是(OI)中常用的一种线性数据结构,请注意,本文主要讲的是栈这种数据结构,而非程序运行时的系统栈/栈空间。
栈的修改是按照后进先出的原则进行的,因此栈通常被称为是后进先出((last~ ~in~ ~first~ ~out))表,简称 LIFO 表。
元素访问:
s.top()
返回栈顶
容量:
s.empty()
返回是否为空
s.size()
返回元素数量
修改:
s.push()
插入传入的参数到栈顶
s.pop()
弹出栈顶
队列
队列((queue))是一种具有「先进入队列的元素一定先出队列」性质的表。由于该性质,队列通常也被称为先进先出((first in first out))表,简称 FIFO 表。
队列模拟
数组模拟队列
通常用一个数组模拟一个队列,用两个变量标记队列的首尾。
-
插入元素:
q[++qr]=x;
-
删除元素:
++ql;
-
访问队首/队尾
q[ql]
/q[qr]
-
清空队列
ql=1;qr=0;
双栈模拟队列
还有一种冷门的双栈模拟队列
这种方法使用两个栈F,S模拟一个队列,其中F十队尾的栈,S代表队首的栈,支持push(在对未插入),pop(在队首插入)操作:
-
push:插入到栈F中。
-
pop:如果S非空,让S弹栈否则把F的元素倒过来压到S中(其实就是一个一个弹出插入,昨晚后十首尾颠倒的),然后再让S弹栈。
容易证明,每个元素只会进入/转移/弹出一次,均摊复杂度(O(1))。
特殊的的队列
双端队列
双端队列是指一个可以在队首/队尾插入或删除元素的队列。
相当于十栈和队列功能的结合。
具体地,双端队列支持的操作有4个;
- 在队首插入一个元素
- 在队尾插入一个元素
- 在队首删除一个元素
- 在队尾删除一个元素
循环队列
使用数组模拟队列会导致一个问题:随着时间的退役,整个队列会向数组的尾部移动,一旦到达数组的最末端,即使数组的前端还有空闲位置,再进行入队操作也会导致溢出(这种数组里实际有空闲位置而发生了上溢的现象称为“假溢出”)。
解决假溢出的办法是采用循环的方式来组织存放队列元素的数组,即将数组下标为0的未知看做是最后一个位置后继。(数组下标为x
的元素,它的后继为(x + 1) % SIZE
)。这样就形成了循环队列。