我们知道,队列的特点是:先进先出(FIFO), 而栈的特点是:先进后出(FILO);
这两个数据结构的特点很像生活中的排列买票过程和坐电梯的过程(当然,是只有一个门打开的电梯);
在Python中,我们可以使用List来模拟这两个数据结构,可以通过限制List的行为来完成对这两种数据结构的模拟:让List只有append和默认pop的行为则模拟成栈,让List只有append和pop(0)的行为则模拟成队列;
那,当我们只有栈这种结构存在时,有没有办法得到一个队列呢,我们稍加思考就会发现:
在S1,S2两个栈处理后,也就是经过这两次push-> pop, 我们发现进入到S1中的a,b,c,从S2中出来的仍然是a,b,c;
所以,如果我们把S1,S2两个栈作为一个队列实现的暗箱,就完成了这两个栈实现队列的过程;
当然了,弄清了基本的原理,那么实现代码就很容易了。直接上代码:
# Python的代码实现
class QueueWithStacks:
def __init__(self):
self.s1 = [ ]
self.s2 = [ ]
# push很简单,让节点直接进入栈S1
def push(self, e):
self.s1.append(e)
# pop的操作要复杂点,原则上是将S1中的节点输入到S2,从S2中pop出来的元素一定是满足FIFO的顺序的
def pop(self):
if (len(self.s2) <= 0):
while (len(self.s1) > 0): # 将S1中的元素依次Push到S2中;
t = self.s1.pop(len(self.s1)-1)
self.s2.append(t)
assert(len(self.s2) > 0) # 此时,需要保证S2中一定有元素,否则,逻辑上的队列是没有元素可以输出的;
return self.s2.pop(len(self.s2)-1)
# 显示当前封装队列的两个栈当前信息
#def __repr__(self):
# print("s1:",self.s1)
# print("s2:",self.s2)
# 测试代码
q = QueueWithStacks()
q.push('a')
q.push('b')
q.push('c')
print(q.pop())
q.push('d')
print(q.pop())
print(q.pop())
print(q.pop())
在Q1,Q2两个队列中,我们可以使用一下的规则来模拟出一个栈:开始时,Q1进行push数据;以后,Q1与Q2不为空的进行push数据;pop时,将不为空的队列数据挨个push到空队列,直到剩一个元素为止,打印这个元素并删除;
由此,我们得到下面的Python代码:
class StackWithQueues(object):
def __init__(self):
self.stack1 = []
self.stack2 = []
# 刚开始,队列1进行push数据;以后,选择队列1与队列2不为空的进行push数据
def push(self,x):
if len(self.stack1) == 0 and len(self.stack2) == 0:
self.stack1.append(x)
elif len(self.stack1) == 0 and len(self.stack2) > 0:
self.stack2.append(x)
elif len(self.stack2) == 0 and len(self.stack1) > 0:
self.stack1.append(x)
else:
assert(1 == 0)
# pop时,将不为空的队列数据挨个push到空队列,直到剩一个元素为止,打印这个元素并删除
def pop(self):
if len(self.stack1) > 0 and len(self.stack2) == 0:
while len(self.stack1) > 1:
self.stack2.append(self.stack1.pop(0))
return self.stack1.pop(0)
elif len(self.stack2) > 0 and len(self.stack1) == 0:
while len(self.stack2) > 1:
self.stack1.append(self.stack2.pop(0))
return self.stack2.pop(0)
else:
assert(1==0)
# 输出信息
# def __repr__(self):
# if self.stack1:
# return self.stack1.__str__()
# else:
# return self.stack2.__str__()
# 测试代码
s = StackWithQueues()
s.push(1)
s.push(2)
s.push(3)
print(s.pop())
print(s.pop())
print(s.pop())
这样的练习有助于更加灵活深入的理解数据结构的概念,所以在面试时经常出现。