代码随想录day 10:栈与队列01(理论基础,用栈实现队列,用队列实现栈)

1. 理论基础

栈即stack,采用的是Last in first out的方法。队列即queue,采用的是first in first out的方法。

stack的基本操作:

Stack 类具有以下方法:

  • push()
  • pop()
  • peek()
  • size()
  • isEmpty()

其中,pop() 是弹栈操作,返回栈顶元素,peek() 只是返回栈顶元素值,不弹栈!

(参考Python 数据结构 —— Stack_python stack-CSDN博客

在python中,stack主要由list来实现:

class Stack:
	def __init__(self):
		self.items = []

	def push(self, item):
		self.items.append(item)

	def pop(self):
		return self.items.pop()

	def peek(self):
		return self.items[len(self.items)-1]

	def size(self):
		return len(self.items)

	def isEmpty(self):
		return self.items == []

(原文链接: https://blog.csdn.net/qq_41140138/article/details/118462018)

  • 栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。
  • 栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。比如(list,listnode,vector)

2. 用栈实现队列(leetcode 232)

这道题考察的主要是对stack和queue的理解程度,不涉及什么算法内容。

这题我们需要设置一个input stack和一个output stack。

在push的时候将数据都放入input stack,在pop的时候若output stack为空,将input stack内容导入output stack来进行pop。若数据不为空,则直接导出output stack的数据。

peak也是直接运用pop的思路,只是不导出数据。

class MyQueue:

    def __init__(self):
        #设置我们的input和output stack
        self.stack_in = []
        self.stack_out = []
        

    def push(self, x: int) -> None:
        #在input stack中放入我们的新元素
        self.stack_in.append(x)

    def pop(self) -> int:
        if self.empty():
            return None
        #判断output stack是否有元素来决定是否导入input stack数据
        if self.stack_out:
            return self.stack_out.pop()
        else:
            #若没有,按input的反顺序导入output,再pop,此时变为first in first out
            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:
        ans = self.pop()
        self.stack_out.append(ans) #注意这里我们数据已经在output了
        return ans

    def empty(self) -> bool:
        return not (self.stack_in or self.stack_out)

这题要关键点在于如何用first in last out的特性来实现first in first out。我们需要巧妙地多运用一个output stack来反向输入input stack的数据,这样就能反转out的顺序,变成first in first out。

接下来我们看看如何运用queue来实现stack。

3. 用队列实现栈(leetcode 225)

这题其实思路和上一题一样,我们也是设置一个两个queue,然后利用两个queue first in first out的特性,在pop的时候讲两个queue中其他的元素传到each other那里,这样剩下的元素就是我们last in的元素,first out出去。

这题和上一题不同的点在于队伍的顺序在交换时是没有改变的。相当于正正得正,但是保留了一部分,上一题是相当于负负得正,交换时调换了顺序。

图源:代码随想录。正如这张图,把3和1调换到queue2,然后out我们的4。

from collections import deque

class MyStack:

    def __init__(self):
        """
        Python普通的Queue或SimpleQueue没有类似于peek的功能
        也无法用索引访问,在实现top的时候较为困难。

        用list可以,但是在使用pop(0)的时候时间复杂度为O(n)
        因此这里使用双向队列,我们保证只执行popleft()和append(),因为deque可以用索引访问,可以实现和peek相似的功能

        in - 存所有数据
        out - 仅在pop的时候会用到
        """
        self.queue_in = deque()
        self.queue_out = deque()

    def push(self, x: int) -> None:
        """
        直接append即可
        """
        self.queue_in.append(x)


    def pop(self) -> int:
        """
        1. 首先确认不空
        2. 因为队列的特殊性,FIFO,所以我们只有在pop()的时候才会使用queue_out
        3. 先把queue_in中的所有元素(除了最后一个),依次出列放进queue_out
        4. 交换in和out,此时out里只有一个元素
        5. 把out中的pop出来,即是原队列的最后一个
        
        tip:这不能像栈实现队列一样,因为另一个queue也是FIFO,如果执行pop()它不能像
        stack一样从另一个pop(),所以干脆in只用来存数据,pop()的时候两个进行交换
        """
        if self.empty():
            return None

        for i in range(len(self.queue_in) - 1):
            self.queue_out.append(self.queue_in.popleft())
        
        self.queue_in, self.queue_out = self.queue_out, self.queue_in    # 交换in和out,这也是为啥in只用来存
        return self.queue_out.popleft()

    def top(self) -> int:
        """
        写法一:
        1. 首先确认不空
        2. 我们仅有in会存放数据,所以返回第一个即可(这里实际上用到了栈)
        写法二:
        1. 首先确认不空
        2. 因为队列的特殊性,FIFO,所以我们只有在pop()的时候才会使用queue_out
        3. 先把queue_in中的所有元素(除了最后一个),依次出列放进queue_out
        4. 交换in和out,此时out里只有一个元素
        5. 把out中的pop出来,即是原队列的最后一个,并使用temp变量暂存
        6. 把temp追加到queue_in的末尾
        """
        # 写法一:
        # if self.empty():
        #     return None
        
        # return self.queue_in[-1]    
        # 这里实际上用到了栈,因为直接获取了queue_in的末尾元素

        # 写法二:
        if self.empty():
            return None

        for i in range(len(self.queue_in) - 1):
            self.queue_out.append(self.queue_in.popleft())
        
        self.queue_in, self.queue_out = self.queue_out, self.queue_in 
        temp = self.queue_out.popleft()   
        self.queue_in.append(temp)
        return temp


    def empty(self) -> bool:
        """
        因为只有in存了数据,只要判断in是不是有数即可
        """
        return len(self.queue_in) == 0

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值