栈和队列(1)----实现

一、题一

1、设计一个有getMin功能的栈

题目:实现一个特殊的栈,在实现栈的基本功能基础上,再实现返回栈中最小元素的操作。

要求:(1)pop、push、getMin操作的时间复杂度都是O(1)。(2)设计的栈类型可以使用现成的栈结构。

2、思路:

使用两个栈,一个栈保存当前栈中的元素,记做stackData;一个栈保存最小值的栈,记做stackMin,栈顶数据为最小的数据。

两个栈使用方案:

push【压入数据】:

假设要压入数据 x ,先压入原始栈 stackData,

然后判断stackMin是否为空,如果空,直接将 x 也压入stackMin。

如果不为空,则将 x 和 stackMin 栈顶数据比较大小,

如果 x 较小或相等,则将其压入stackMin;

如果 x 较大,则不压。

 

pop【弹出数据】:

 从原始栈 stackData先弹出元素,记为data,然后比较当前stackMin的栈顶元素和data相等还是不等,【原因是stackMin中元素肯定比data小或者相等】。如果不等,则不操作,如果相等,则将stackMin的栈顶元素弹出。

getMin【查询最小值】:

 返回stackMin中的栈顶元素。

 

3、代码:

import queue
class Stack():
    def __init__(self):
        self.stack = queue.LifoQueue()
        self.stackMin = queue.LifoQueue()
    def pop(self):
        value = self.stack.get()
     if self.stackMin.empty():
      print("is empyty")
valueMin
= self.stackMin.get() if value != self.stackMin.get(): self.stackMin.put(valueMin) def push(self,x): self.stack.put(x) if self.stackMin.empty(): self.stackMin.put(x) else: value = self.stackMin.get() if x <= value: self.stackMin.put(value) self.stackMin.put(x) else: self.stackMin.put(value) def getMin(self): value = self.stackMin.get() self.stackMin.put(value) return value a = Stack() a.push(1) a.push(3) a.push(0) a.push(9) a.pop() print(a.getMin())

 


二、题二

1、由两个栈实现队列:

思路一:将stack1作为存储空间,将stack2作为临时缓冲区,入队时,直接压入stack1,出队时,将stack1中的元素依次出栈压入stack2中,再将stack2的栈顶元素弹出,最后将stack2中的元素再倒回给stack1

思路二:入队时,判断stack1是否为空,如果stack1为空,则将stack2中的所有元素都倒入stack1中,再将元素直接压入stack1,否则,直接压入stack1中  

           出队时,判断stack2是否为空,如果stack2为空,则将stack1中的元素倒入stack2中,在将stack2的栈顶元素弹出,否则,直接弹出stack2的栈顶元素

2、思路三:

入队时,直接压入stack1中

出队时,判断stack2是否为空,如果stack2为空,则将stack1中的元素倒入stack2中,否则直接弹出stack2中的元素

思路一与思路二相比,如果是连续出栈操作或连续进栈操作,思路二比思路一好很多。思路三最好。

详细介绍思路三如下:

stackPush栈只压入数据,stackPop只做弹出栈。

 

 实现流程:

push:往stackPush插入;

pop:首先判断stackPop是否为空,如果空则把stackPush压入stackPop,除了其栈底元素。

  如果不为空,则直接将stackPop中的栈顶元素删除;

例子:

先插入 a,b,c【往栈1压】;

删除 a 【栈2中没有元素,则将栈1的元素倒入栈2中,除了栈底的元素】; 

再删除b【栈2有元素,则将栈2栈顶数据删除】

再插入d【加入栈1】

再删除c 【栈2没空,则删除栈2栈顶元素】

3、代码:

import queue
class builtqueue():
    def __init__(self):
        self.stackPush = queue.LifoQueue()
        self.stackPop = queue.LifoQueue()
    def push(self,x):
        self.stackPush.put(x)
    def pop(self):
        if self.stackPop.empty():
            while not self.stackPush.empty():
                self.stackPop.put(self.stackPush.get())
        return self.stackPop.get()
        
a = builtqueue()
a.push('a')
a.push('b')
a.push('c')
print(a.pop())
print(a.pop())
a.push('d')
print(a.pop())

 


三、题三

1、两个队列实现一个栈:

2、思路:

 将queue1用作进栈出栈,queue2作为一个中转站

入栈时,直接压入queue1中

出栈时,先将queue1中的元素除最后一个元素外依次出队列,并压入队列queue2中,将留在queue1中的最后一个元素出队列即为出栈元素,最后还要把queue2中的元素再次压入queue1中


 

四、题四:栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:

  建立一个辅助栈stack,

  每次判断辅助栈stack顶部元素和popV的第一个元素是否一样,【一样则popV.pop(0)且stack.pop()】

  然后判断pushV[i] 和popV的第一个元素是否一样,【一样则popV.pop(0)且 i += 1】

    若不一样则stack.append(pushV[i])

 总体:

  建立一个辅助栈s,把序列1,2,3,4,5依次压入辅助栈s,并按照第二个序列4,5,3,2,1的顺序从辅助栈s中弹出数字。

  先将序列1,2,3,4,5依次压入栈s,每次压栈时都判断栈s的当前栈顶元素跟序列4,5,3,2,1的第一个元素是否相等。当压入4之后,发现栈顶元素跟序列4,5,3,2,1的第一个元素相等。弹出栈s的栈顶元素4,然后将序列4,5,3,2,1中第一个元素去掉,序列4,5,3,2,1变成序列5,3,2,1。在执行上述过程。

代码:

  

    def IsPopOrder(self, pushV, popV):
        # write code here
        if not pushV:
            return True
        stack = []
        i = 0
        while i < len(pushV):
            while stack and stack[-1] == popV[0]:
                popV.pop(0)
                stack.pop()
            if pushV[i] == popV[0]:
                popV.pop(0)
                i += 1
            else:
                stack.append(pushV[i])
                i += 1
        while popV:
            if popV[0] != stack[-1]:
                return False
            else:
                popV.pop(0)
                stack.pop()
        return True

 

posted on 2018-09-22 21:16  吱吱了了  阅读(516)  评论(0编辑  收藏  举报

导航