分类目录:《算法设计与分析》总目录
相关文章:
·栈和队列
·利用collections.deque模块实现双向队列
栈和队列都是动态集合,且在其上进行删除操作所移除的元素是预先设定的。在栈中,被删除的是最近插入的元素:栈实现的是一种后进先出策略。类似地,在队列中,被删去的总是在集合中存在时间最长的那个元素:队列实现的是一种先进先出策略。在计算机上实现栈和队列有几种有效方式。本文将介绍如何利用一个简单的数组实现这两种结构。
栈
栈上的插入操作称为压入,而无元素参数的删除操作称为弹出。这两个名称使人联想到现实中的栈,比如餐馆里装有弹簧的摞盘子的栈。盘子从栈中弹出的次序刚好同它们压入的次序相反,这是因为只有最上面的盘子才能被取下来。
如下图所示,可以用一个数组
S
[
1
⋯
n
]
S[1\cdots n]
S[1⋯n]来实现一个最多可容纳
n
n
n个元素的栈。该数组有一个属性
S
.
t
o
p
S.top
S.top,指向最新插入的元素。栈中包含的元素为
S
[
1
⋯
S
.
t
o
p
]
S[1\cdots S.top]
S[1⋯S.top],其中
S
[
1
]
S[1]
S[1]是栈底元素,而
S
[
S
.
t
o
p
]
S[S.top]
S[S.top]是栈顶元素。
当
S
.
t
o
p
=
0
S.top=0
S.top=0时,栈中不包含任何元素,即栈是空的。如果试图对一个空栈执行弹出操作,则称栈下溢,这通常是一个错误。如果
S
.
t
o
p
S.top
S.top超过了
n
n
n,则称栈上溢。栈的几种操作只需分别用几行代码来实现:
class Stack(object):
def __init__(self):
self.stack = []
def push(self, data):
"""
进栈函数
"""
self.stack.append(data)
def pop(self):
"""
出栈函数,
"""
self.stack.pop()
def gettop(self):
"""
取栈顶
"""
return self.stack[-1]
队列
队列上的插入操作称为入队,删除操作称为出队;正如栈的删除操作一样,出队操作也没有元素参数。队列的先进先出特性类似于收银台前排队等待结账的一排顾客。队列有队头和队尾,当有一个元素入队时,它被放在队尾的位置,就像一个新到来的顾客排在队伍末端一样。而出队的元素则总是在队头的那个,就像排在队伍前面等待最久的那个顾客一样。
下图表明利用数组
Q
[
1
⋯
n
]
Q[1\cdots n]
Q[1⋯n]来实现一个最多容纳
n
−
1
n-1
n−1个元素的队列的一种方式。该队列有一个属性
Q
.
h
e
a
d
Q.head
Q.head指向队头元素。而属性
Q
.
t
a
i
l
Q.tail
Q.tail则指向下一个新元素将要插入的位置。队列中的元素存放在位置
Q
.
h
e
a
d
,
Q
.
h
e
a
d
+
1
,
⋯
,
Q
.
t
a
i
l
−
1
Q.head, Q.head + 1, \cdots , Q.tail - 1
Q.head,Q.head+1,⋯,Q.tail−1,并在最后的位置“环绕”,感觉好像位置1紧邻在位置
n
n
n后面形成一个环序。当
Q
.
h
e
a
d
=
Q
.
t
a
i
l
Q.head=Q.tail
Q.head=Q.tail时,队列为空。初始时有
Q
.
h
e
a
d
=
Q
.
t
a
i
l
=
1
Q.head=Q.tail=1
Q.head=Q.tail=1。如果试图从空队列中删除一个元素,则队列发生下溢。当
Q
.
h
e
a
d
=
Q
.
t
a
i
l
+
1
Q.head=Q.tail+1
Q.head=Q.tail+1时,队列是满的,此时若试图插入一个元素,则队列发生上溢。