栈与队列

一、栈

  • 特性:

    • 先进后出

    • 从栈顶向栈底添加元素,从栈顶取元素
  • 栈的操作

    • Stack() :创建一个新的空栈
    • push(item) :添加一个新的元素item到栈顶
    • pop() :弹出栈顶元素
    • peek() :返回栈顶元素
    • is_empty(): 判断栈是否为空
    • size(): 返回栈的元素个数
  • 栈的实现

    class Stack:
        """"""
        def __init__(self):
             self.items = []
    
        def is_empty(self):
            """判断是否为空"""
            return 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)
    
    if __name__ == "__main__":
        stack = Stack()
        stack.push("hello")
        stack.push("world")print (stack.size())
        print (stack.peek())
        print (stack.pop())

二、队列

  • 特性:

    • 先进先出
    • 只允许从队尾插入元素,从队头取元素
  • 操作:

    • Queue() :创建一个空的队列
    • enqueue(item) :往队列中添加一个item元素
    • dequeue() :从队列头部删除一个元素
    • is_empty() :判断一个队列是否为空
    • size() :返回队列的大小
  • 队列实现:

    class Queue:
        '''队列'''
        def __init__(self):
            self.items = []
    
        def enqueue(self,item):
            '''入队列'''
            self.items.insert(0,item)
    
        def dequeue(self):
            '''出队列'''
            return self.items.pop()
    
        def is_empty(self):
            '''判空'''
            return self.items == []
    
        def size(self):
            '''大小'''
            return len(self.items)
    
    if __name__ == "__main__":
        q = Queue()
        q.enqueue("hello")
        q.enqueue("world")
        print(q.size())
        print(q.dequeue())
  • 案例

    • 烫手的山芋:
      • 6个孩子围成一个圈,排列顺序由自己指定。第一个孩子手里有一个烫手的山芋,需要在计时器计时开始1秒后传递给下一个孩子,以此类推。规则是:计时器每计时7秒时,就会淘汰手里有山芋的孩子,该游戏直到剩下最后一个孩子结束,该孩子获胜。请用队列实现该游戏策略,排在第几个孩子最终获胜。
    • 分析:
      • 队列特性:先进先出,并且只能从队尾插入数据,从队头取数据。
      • 第1秒时,山芋在第1个孩子手里,第2秒时在第2个孩子手里,以此类推,第7秒时,该轮游戏中山芋被传递了6次
      • 可以将手里有山芋的孩子始终放在队头位置:每传递一次,队头孩子出队列,然后再入队列,每轮结束时,队头孩子出队列
    • 代码实现:
      # coding:utf-8
      
      class Queue:
          '''队列'''
          def __init__(self):
              self.items = []
      
          def enqueue(self,item):
              '''入队列'''
              self.items.insert(0,item)
      
          def dequeue(self):
              '''出队列'''
              return self.items.pop()
      
          def is_empty(self):
              '''判空'''
              return self.items == []
      
          def size(self):
              '''大小'''
              return len(self.items)
      
      def shanyu_game():
          '''烫手的山芋游戏'''
      
          kids = [1,2,3,4,5,6] #1-6分别表示一开始对应位置上的孩子
          q = Queue()
          for kid in kids:
              q.enqueue(kid)
          while q.size() > 1:
              for i in range(6):
                  kid = q.dequeue() #出队列
                  q.enqueue(kid) #入队列
              q.dequeue()
          print('第%s个孩子获胜'%q.dequeue())
      
      
      if __name__ == "__main__":
         shanyu_game()

       运行结果:第5个孩子获胜

 三、双端队列

  • 特性

    • 是一种具有队列和栈的性质的数据结构。
    • 可以在队列任意一端入队和出队。
  • 操作

    • Deque() :创建一个空的双端队列
    • add_front(item) :从队头加入一个item元素
    • add_rear(item) :从队尾加入一个item元素
    • remove_front() :从队头删除一个item元素
    • remove_rear(): 从队尾删除一个item元素
    • is_empty(): 判断双端队列是否为空
    • size(): 返回队列的大小
  • 实现

    class Deque:
        '''双端队列'''
    
        def __init__(self):
            self.items = []
    
        def add_front(self,item):
            '''队头插入元素'''
            self.items.insert(0,item)
    
        def add_rear(self,item):
            '''队尾插入元素'''
            self.items.append(item)
    
        def remove_front(self):
            '''队头删除元素'''
            return self.items.pop(0)
    
        def remove_rear(self):
            '''队尾删除元素'''
            return self.items.pop()
    
        def size(self):
            '''返回队列大小'''
            return len(self.items)
    
    if __name__ == '__main__':
        d = Deque()
        d.add_front('a')
        d.add_front('b')
        d.add_rear('c')
        d.add_rear('d')
        print(d.remove_front())
        print(d.remove_rear())
        print(d.size())
  • 案例

    • 回文检查:判断字符串首尾字符是否相同,例如madam,toot
    • 代码实现:
      # coding:utf-8
      class Deque:
          '''双端队列'''
      
          def __init__(self):
              self.items = []
      
          def add_front(self,item):
              '''队头插入元素'''
              self.items.insert(0,item)
      
          def add_rear(self,item):
              '''队尾插入元素'''
              self.items.append(item)
      
          def remove_front(self):
              '''队头删除元素'''
              return self.items.pop(0)
      
          def remove_rear(self):
              '''队尾删除元素'''
              return self.items.pop()
      
          def size(self):
              '''返回队列大小'''
              return len(self.items)
      
      def palindrome_checker(item):
          '''回文检查器'''
          d = Deque()
          for i in item:
              d.add_rear(i)
          while d.size() > 1:
              start = d.remove_front()
              end = d.remove_rear()
              #判断首位字符是否相等,不相等即返回False
              if start != end:
                  return False
          return True
      
      if __name__ == '__main__':
          print(palindrome_checker('hello'))
          print(palindrome_checker('abbccbba'))
          print(palindrome_checker('abcdcba'))

 

四、使用栈实现队列

  • 分析:

    • 使用栈实现队列,即实现先进先出的特性
    • 可以采用两个栈来实现
      • 栈A提供入队列功能
      • 栈B提供出队列功能
        • 若栈B为空,则先将栈A中的数据依次弹出,放入栈B,再弹出栈B的最后一个数据
        • 若栈B不为空,则直接弹出栈B的最后一个数据
  • 代码实现:

    # coding:utf-8
    
    class Stack:
        """"""
        def __init__(self):
             self.items = []
    
        def is_empty(self):
            """判断是否为空"""
            return 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)
    
    class MyQueue:
        '''栈实现队列'''
        def __init__(self):
            self.A = Stack()
            self.B = Stack()
    
        def push(self,item):
            '''入队列'''
            self.A.push(item)
    
        def pop(self):
            '''出队列'''
            if self.B.is_empty():
                while not self.A.is_empty():
                    self.B.push(self.A.pop())
            return self.B.pop()
    
    if __name__ == '__main__':
        q = MyQueue()
        q.push('a')
        q.push('b')
        q.push('c')
        print(q.pop())
        print(q.pop())
        print(q.pop())

五、使用队列实现栈

  • 分析

    • 使用队列实现栈,即实现先入后出的特性
    • 可以采用两个队列来实现
      • 队列A负责入栈操作
      • 出栈操作时,队列A中仅保留队尾一个数据,其余数据全部入队列B,然后队列A和队列B互换,取出队列B中的一个数据
  • 代码实现

    class Queue:
        '''队列'''
        def __init__(self):
            self.items = []
    
        def enqueue(self,item):
            '''入队列'''
            self.items.insert(0,item)
    
        def dequeue(self):
            '''出队列'''
            return self.items.pop()
    
        def is_empty(self):
            '''判空'''
            return self.items == []
    
        def size(self):
            '''大小'''
            return len(self.items)
    
    class MyStack:
        '''队列实现的栈'''
        def __init__(self):
            self.A = Queue()
            self.B = Queue()
    
        def push(self,item):
            '''入栈'''
            self.A.enqueue(item)
    
        def pop(self):
            '''出栈'''
            while self.A.size() > 1:
                self.B.enqueue(self.A.dequeue())
            self.A,self.B = self.B,self.A
            return self.B.dequeue()
    
    if __name__ == '__main__':
       stack = MyStack()
       stack.push(1)
       stack.push(2)
       stack.push(3)
       print(stack.pop())
       stack.push(4)
       print(stack.pop())
       print(stack.pop())
       print(stack.pop())

     

 

posted @ 2021-08-17 17:01  eliwang  阅读(56)  评论(0编辑  收藏  举报