代码随想录第十天 | 栈与队列:用栈和队列互相实现

栈与队列理论基础

队列queue是先进先出(FIFO),而栈stack是先进后出 / 后进先出 (LIFO)。由于使用的语言是Python,因此主要用列表List来解释栈stack。

用List来实现栈,需要分清楚栈的头尾。先进入栈的数据如同装进瓶子的石头,会被积压在底部;而后进入栈的数据会在倒瓶子的时候必先进入的数据优先被取出来。因此,队列的头部实际是栈的底部,它会储存最后被导出的数据;而队列的尾部是栈的顶部,接受新的装入栈的数据。装入栈的时候我们可以利用列表的append()往队列的末尾加入新数据,而取出栈顶数据的代码,会根据是用栈实现队列,还是队列实现栈,而有所差异。
在这里插入图片描述


232.用栈实现队列

Leetcode 232 原题链接
本题要求时实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾。队列的尾部就是指栈顶,也就是要将元素x作为最后一个压入栈的元素。

int pop()队列的开头移除并返回元素。队列的开头就是指栈底,指栈的最下面的元素,也就是最先被压入栈的元素。

int peek() 返回队列开头的元素。

boolean empty() 如果队列为空,返回 true ;否则,返回 false

输入栈和输出栈

在push数据的时候,只要数据放进输入栈就好;但在pop的时候,操作就复杂一些,需要两个栈,一个是储存数据的输入栈,一个则是完成弹出操作的输出栈:输出栈如果为空,就把进栈数据全部导入进来,再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。

输入栈和输出栈的方向是相反的。输入栈 stack_in 用于存储原始的元素顺序,而输出栈 stack_out 用于存储元素的逆序。

当需要从队列中弹出元素时,先检查输出栈是否为空。如果输出栈不为空,则直接从输出栈的底部弹出元素,这样可以保证先入先出的顺序。如果输出栈为空,则将输入栈中的元素逐个弹出,并依次推入输出栈,以实现先入先出的效果。

因此,输入栈和输出栈在逻辑上是相反的,输入栈存储的是原始的元素顺序,而输出栈存储的是元素的逆序。此时,要注意,下图中的输出栈实际方向为从右往左,和左边的输入栈方向已经相反了。
在这里插入图片描述

class MyQueue:

    def __init__(self):
        self.stack_in = []
        self.stack_out = []

    def push(self, x: int) -> None:
        self.stack_in.append(x)
        
    def pop(self) -> int:
        if self.empty():
            return None
        if self.stack_out:
            return self.stack_out.pop()
            # 这里的pop()不同于我们命名的function,pop()是移除并返回列表中的最后一个元素
        else:
            for i in range(len(self.stack_in)):
                self.stack_out.append(self.stack_in.pop())
            return self.stack_out.pop()
            
    def peek(self) -> int:
        # 要的就是pop(self)返回的开头元素
        ans=self.pop() # 这是上面命名的pop()
        self.stack_out.append(ans) # 运行pop(self)把该元素从输出栈里移除了,要重新加进去
        return ans
        
    def empty(self) -> bool:
        return not (self.stack_in or self.stack_out)
        # 只要in或者out有元素,说明队列不为空

# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

225. 用队列实现栈

Leetcode 225 原题链接
本题要求实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。也就是在队列的尾部插入新元素。

int pop() 移除并返回栈顶元素。也就是移除并返回队列尾部元素。

int top() 返回栈顶元素。

boolean empty() 如果栈是空的,返回 true ;否则,返回 false

不同于用栈实现队列的时候需要构建输入栈和输出栈,用队列实现栈只需要一个队列即可解决。

class MyStack:

    def __init__(self):
        self.stack=[]

    def push(self, x: int) -> None:
        # 压入栈顶等于是放在最上面,相等于放到列表的后面
        self.stack.append(x)

    def pop(self) -> int:
        ans=self.top() # 先找到栈顶元素,也就是列表末尾元素
        self.stack.pop() # 移除该元素
        return ans

    def top(self) -> int:
        return self.stack[-1] # 返回栈顶元素,也就是列表末尾元素

    def empty(self) -> bool:
        # return True if not self.stack else False
        return self.stack==[]

# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值