数据结构与算法 栈 队列 双端队列
栈
- 特性:先进后出的数据结构
- 栈顶,栈尾
- 应用:每个 web 浏览器都有一个返回按钮。当你浏览网页时,这些网页被放置在一个栈中(实际是网页的网址)。你现在查看的网页在顶部,你第一个查看的网页在底部。如果按‘返回’按钮,将按相反的顺序浏览刚才的页面。
---------------------
- Stack() 创建一个空的新栈。 它不需要参数,并返回一个空栈。
- push(item)将一个新项添加到栈的顶部。它需要 item 做参数并不返回任何内容。
- pop() 从栈中删除顶部项。它不需要参数并返回 item 。栈被修改。
- peek() 从栈返回顶部项,但不会删除它。不需要参数。 不修改栈。
- isEmpty() 测试栈是否为空。不需要参数,并返回布尔值。
- size() 返回栈中的 item 数量。不需要参数,并返回一个整数。
class Stack(): def __init__(self): self.items=[] # 添加数据 进栈 def push(self,item): self.items.append(item) #取出数据 出栈 def pop(self): return self.items.pop() def isEmpty(self): return self.items==[]
def size(self): return len(self.items)
def peek(self): return self.items[len(self.items)-1]
def show(self): return self.items stack=Stack() stack.push(1) stack.push(2) stack.push(3) print(stack.show()) # print(stack.pop()) # print(stack.pop()) # print(stack.peek()) print(stack.isEmpty())
网页访问模拟
s=Stack() def getRequest(url): s.push(url) def showcurrenturl(): print('当前页面',s.peek()) def back(): s.pop() print('回退按钮点击后显示的url:',s.peek()) getRequest('www.1.com') getRequest('www.2.com') getRequest('www.3.com') getRequest('www.4.com') showcurrenturl() showcurrenturl() back() back() showcurrenturl() back()
队列
- 队列:先进先出
- 应用场景:
- 我们的计算机实验室有 30 台计算机与一台打印机联网。当学生想要打印时,他们的打印任务与正在等待的所有其他打印任务“一致”。第一个进入的任务是先完成。如果你是最后一个,你必须等待你前面的所有其他任务打印
- Queue() 创建一个空的新队列。 它不需要参数,并返回一个空队列。
- enqueue(item) 将新项添加到队尾。 它需要 item 作为参数,并不返回任何内容。
- dequeue() 从队首移除项。它不需要参数并返回 item。 队列被修改。
- isEmpty() 查看队列是否为空。它不需要参数,并返回布尔值。
- 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 isEmpty(self): return self.items==[] def size(self): return len(self.items) def show(self): return self.items q=Queue() q.enqueue(1) q.enqueue(2) q.enqueue(3) print(q.show()) print(q.dequeue()) print(q.dequeue()) print(q.isEmpty()) print(q.size())
结果: [3, 2, 1] 1 2 False 1
- 案例:烫手的山芋
- 烫手山芋游戏介绍:6个孩子围城一个圈,排列顺序孩子们自己指定。第一个孩子手里有一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下一个孩子,依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一个孩子时结束,最后剩下的孩子获胜。请使用队列实现该游戏策略,排在第几个位置最终会获胜。
- 结论:
- 七秒即时到了之后,山芋被传递了6次。
- 保证手里有山芋的孩子永远站在队列的头部
q=Queue() kids=['a','b','c','d','e','f'] for kid in kids: q.enqueue(kid) # print(q.show()) while q.size()>1: for i in range(6): # 内层循环是用来将手里有山芋的孩子排在队头 kid=q.dequeue() q.enqueue(kid) q.dequeue() print(q.dequeue()) #结果 e
双端队列
- 同同列相比,有两个头部和尾部。可以在双端进行数据的插入和删除,提供了单数据结构中栈和队列的特性
- Deque() 创建一个空的新 deque。它不需要参数,并返回空的 deque。
- addFront(item) 将一个新项添加到 deque 的首部。它需要 item 参数 并不返回任何内容。
- addRear(item) 将一个新项添加到 deque 的尾部。它需要 item 参数并不返回任何内容。
- removeFront() 从 deque 中删除首项。它不需要参数并返回 item。deque 被修改。
- removeRear() 从 deque 中删除尾项。它不需要参数并返回 item。deque 被修改。
- isEmpty() 测试 deque 是否为空。它不需要参数,并返回布尔值。
- size() 返回 deque 中的项数。它不需要参数,并返回一个整数
class Dequeue(): def __init__(self): self.items = [] # 从队列头部插入数据 def addFront(self, item): self.items.insert(0, item) # 从队列尾部插入数据 def addRear(self, item): self.items.append(item) # 队头取出元素 def removeFront(self): return self.items.pop() # 队尾取元素 def removeRear(self): return self.items.pop(0) def size(self): return len(self.items) q=Dequeue() q.addFront(1) q.addFront(2) q.addFront(3) print(q.removeFront()) print(q.removeRear())
双端队列应用案例:回文检查
- 回文是一个字符串,读取首尾相同的字符,例如,radar toot madam。
def huiwen(s): de=Dequeue() flag=True for i in s: de.addFront(i) while de.size()>1: if de.removeFront()!=de.removeRear(): flag=Fale return flag print(huiwen('abcdcba'))