栈(stack)队列(Queue)
-
简单的栈跟队列也是一维结构,类似数组(array);所以分配固定的空间内存,需要考虑空间被占满。存储结构参考链表与数组(线性存储和链接存储)
-
栈是一个一端受限的线性表。类似竖着的柱子,只能从顶端即栈顶进栈或出栈,所以也能得出后进先出。
-
队列是能在两端进行操作的线性表。类似一个管道(pipeline),从一端进入另一端推出即先进先出。
存储形式
如下图
代码表现
栈(stack)
在python语言中通常用list来
stack = ["Amar", "Akbar", "Anthony"]
stack.append("Ram")
stack.append("Iqbal") #进栈
print(stack) # ['Amar', 'Akbar', 'Anthony', 'Ram', 'Iqbal']
print(stack.pop()) # Iqbal
队列(Queue)
同上
stack = ["Amar", "Akbar", "Anthony"]
stack.append("Ram")
stack.append("Iqbal") #进栈
print(stack) # ['Amar', 'Akbar', 'Anthony', 'Ram', 'Iqbal']
print(stack.pop(0)) # Amar
双端队列(deque)
Deque是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,也可以在两端进行插入;即可以在表的两端进行插入和删除操作。
from collections import deque
deque = deque(["Ram", "Tarun", "Asif", "John"])
print(deque) #deque(['Ram', 'Tarun', 'Asif', 'John'])
deque.append("Akbar") #
deque.appendleft("Raj")
print(deque) #deque(['Raj', 'Ram', 'Tarun', 'Asif', 'John', 'Akbar'])
print(deque.pop()) #Akbar
print(deque) #deque(['Raj', 'Ram', 'Tarun', 'Asif', 'John'])
print(deque.popleft()) #Raj
print(deque) #deque(['Ram', 'Tarun', 'Asif', 'John'])
优先队列
优先队列是一个带有优先级的队列。用权重将队列进行排序。在python中,内置的标准库提供了heapq函数模块和PriorityQueue类模块,其中两个模块都是用了堆(heap)的概念。heap是对于每一个父节点上的值都小于或等于子节点的值的二叉树。(堆是另一种数据结构在此不概述,后续完善)
import heapq
from queue import PriorityQueue as PQ # 同步操作,提供锁操作,支持并发的消费者跟生产者
pq = PQ()
pq.put((1, 'a'))
pq.put((2, 'c'))
pq.put((2, 'b'))
pq.put((2, 'b'))
print(pq.queue) # [(1, 'a'), (2, 'b'), (2, 'b'), (2, 'c')]
item0 = pq.get() # (1, 'a')
print(pq.queue) # [(2, 'b'), (2, 'b'), (2, 'c')]
print(pq.qsize()) # 优先队列的尺寸
while not pq.empty():
print(pq.get())
栈与队列的基本题目
1. 判断括号是否合法(栈)
leetcode 20 给定一个s 包含’(',
‘)’,
‘{’,
‘}’,
‘[‘and
’]’ 确定 s是否合法
思路:
给定一个栈,若左边括号则入栈,若右边括号进入则与上一个栈内括号进行消除,若不能消除就Flase,成功则继续,直至栈空。时间复杂度为O(n)。
class Solution:
def isValid(self, s: str) -> bool:
stack=['?']
dic={'(':')','[':']','{':'}','?':'?'}
for i in s:
if i in dic:
stack.append(i)
else:
if dic[stack.pop()] != i:
return False
return len(stack)==1
2. 用栈来实现队列功能
leetcode 232 Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push
, peek
, pop
, and empty
).
class MyQueue:
def __init__(self):
"""
Initialize your data structure here.
"""
self.stack = []
self.temp = []
def push(self, x: int) -> None:
"""
Push element x to the back of queue.
"""
self.temp.append(x) # 临时stack 存值
def pop(self) -> int:
"""
Removes the element from in front of queue and returns that element.
"""
if not self.stack:
while self.temp:
self.stack.append(self.temp.pop()) # 反向存值
return self.stack.pop() # 先进先出
def peek(self) -> int:
"""
Get the front element.
"""
if not self.stack:
while self.temp:
self.stack.append(self.temp.pop())
return self.stack[-1]
def empty(self) -> bool:
"""
Returns whether the queue is empty.
"""
return not self.stack and not self.temp
3. 最小栈
leetcode 155 Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
Implement the MinStack
class:
MinStack()
initializes the stack object.void push(int val)
pushes the elementval
onto the stack.void pop()
removes the element on the top of the stack.int top()
gets the top element of the stack.int getMin()
retrieves the minimum element in the stack.
class MinStack:
def __init__(self):
self.q=[]
def push(self, val: int) -> None:
min_value=self.getMin()
if min_value==None or val < min_value:
min_value=val
self.q.append((val,min_value)) # 栈存入当前值与最小值tuple
def pop(self) -> None:
self.q.pop()
def top(self) -> int:
if len(self.q)==0:
return None
else:
return self.q[-1][0]
def getMin(self) -> int:
if not len(self.q):
return None
else:
return self.q[-1][1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
4. 最长有效括号
Leetcode 32
Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
- 动态规划
class Solution:
def longestValidParentheses(self, s: str) -> int:
dp= [0] * len(s)
len_s=len(s)
for i in range(1,len_s):
if s[i] ==')':
if s[i-1]=='(': # 形成一个有效括号对
dp[i]=dp[i-2]+2
elif i-1-dp[i-1] >0 and s[i-dp[i-1]-1]=='(': #不出界以及跨越两个字符之后又是一个有效括号
dp[i]=dp[i-1]+2+(dp[i-dp[i-1]-2] if i-dp[i-1]-2 >0 else 0) # 取两种判断的和,确定未出界
return max(dp) if s else 0
- 栈
class Solution:
def longestValidParentheses(self, s: str) -> int:
stk, max_len = [(")", -1)], 0
for i in range(len(s)):
if s[i] == ")" and stk[-1][0] == "(":
stk.pop()
max_len = max(max_len, i - stk[-1][1]) # 用序列号获取max_len
else:
stk.append((s[i], i))
return max_len
5. 接雨水
Leetcode 42
Given n
non-negative integers representing an elevation map where the width of each bar is 1
, compute how much water it can trap after raining.
- 栈
class Solution:
def trap(self, height: List[int]) -> int:
stack=[]
res=0
for i in range(len(height)):
while stack and height[i]>height[stack[-1]]:
h=height[stack.pop()] # 单调递减栈
if not stack:
break
res +=min(height[i],height[stack[-1]]-h)*(i-1-stack[-1])
stack.append(i)
return res
- 双指针
class Solution:
def trap(self, height: List[int]) -> int:
if not height or len(height)<3:
return 0
volume=0
left,right=0,len(height)-1
l_max,r_max=height[left],height[right]
while left<right:
l_max,r_max=max(l_max,height[left]),max(r_max,height[right])
if l_max<=r_max:
volume += l_max-height[left]
left +=1
else:
volume +=r_max-height[right]
right -=1
return volume