Python剑指offer之两个栈实现一个队列-两个队列实现一个栈

Python实现数据结构 专栏收录该内容
12 篇文章 8 订阅

栈与队列之间的相互实现,是面试中的经典试题。

两个栈实现一个队列

入队:元素进栈A

出队:先判断栈B是否为空,为空则将栈A中的元素 pop 出来并 push 进栈B,再栈B出栈,如不为空则栈B直接出栈

复杂度分析:

这样用两个栈实现一个队列,入队的复杂度为O(1),出队的复杂度则变为O(n)。

而直接用 python 的单个列表实现队列,以列表首作为队列尾,则入队用insert,复杂度为O(n),出队用pop,复杂度为O(1)。(列表首,即列表中下标为0的元素)

实现:就以列表作为栈的底层实现,只要保证后进先出的约束就是栈。这里只实现入队和出队两个操作。

class Queue:
    def __init__(self):
        self.stockA=[]
        self.stockB=[]
    def push(self, node):
        self.stockA.append(node)
    def pop(self):
        if self.stockB==[]:
            if self.stockA==[]:
                return None
            else:
                for i in range(len(self.stockA)):
                    self.stockB.append(self.stockA.pop())
        return self.stockB.pop()

可以用简单的实例来测试一下是否成功实现了队列

if __name__=='__main__':
    times=5
    testList=list(range(times))
    testQueue=Queue()
    for i in range(times):
        testQueue.push(testList[i])
    print(testList)
    for i in range(times):
        print(testQueue.pop(),',',end='')   #end=''可以让 print 输出不换行
#输出结果:先进先出
[0, 1, 2, 3, 4]
0 ,1 ,2 ,3 ,4 ,

附上牛客网上剑指offer的试题:用两个栈来实现队列

两个队列实现一个栈

进栈:元素入队列A

出栈:判断如果队列A只有一个元素,则直接出队。否则,把队A中的元素出队并入队B,直到队A中只有一个元素,再直接出队。为了下一次继续操作,互换队A和队B。

复杂度分析:

第一种形式:如果以列表尾作为队尾,直接用 append 插入新元素,复杂度为O(1)。

再用pop去弹出队首,也就是列表第0个元素,弹出后插入到另一个队列中。第一次 pop,需要移动列表后面n-1个元素,第二次 pop,需要移动后面n-2个元素……直到最后只剩最后一个元素,直接出队。

复杂度:(n-1)+(n-2)+……+1=O(n^2)。

第二种形式:如果以列表首作为队尾,用 insert 插入新元素,需要移动后面的元素,复杂度则为O(n)。

再用pop去弹出队首,也就是列表最后一个元素,弹出后插入到另一个队列中。这样操作虽然弹出元素的复杂度为O(1),但再插入另一个队列的复杂度则为O(n),因为要连续弹出n-1个元素,则需要连续插入n-1个元素,最后的复杂度同样会是O(n^2)。

因此选择第一种形式。

而直接用python的一个列表实现栈,以列表尾为栈首,则出栈和进栈的复杂度都为O(1)。

实现:就以列表作为队列的底层实现,只要保证先进先出的约束就是队列。这里只实现进栈和出栈两个操作。

class Stock:
    def __init__(self):
        self.queueA=[]
        self.queueB=[]
    def push(self, node):
        self.queueA.append(node)
    def pop(self):
        if len(self.queueA)==0:
            return None
        while len(self.queueA)!=1:
            self.queueB.append(self.queueA.pop(0))
        self.queueA,self.queueB=self.queueB,self.queueA #交换是为了下一次的pop
        return self.queueB.pop()

可以用简单的实例来测试一下是否成功实现了栈

if __name__=='__main__':
    times=5
    testList=list(range(times))
    testStock=Stock()
    for i in range(times):
        testStock.push(testList[i])
    print(testList)
    for i in range(times):
        print(testStock.pop(),',',end='')   
#输出结果:后进先出
[0, 1, 2, 3, 4]
4 ,3 ,2 ,1 ,0 ,
展开阅读全文
  • 9
    点赞
  • 2
    评论
  • 17
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值