栈和队列
1. 栈:后进先出
2. 栈的实现
class Stack: def __init__(self): self.stack = [] def push(self, ele): # 进栈 self.stack.append(ele) def pop(self): # 出栈 self.stack.pop() def get_top(self): # 取栈顶 if len(self.stack) > 0: return self.stack[-1] def is_empty(self): # 判断栈为空 return len(self.stack) == 0
3. 栈的应用:括号匹配问题
def brace_match(str): stack = Stack() # 调用栈对象 match = {'}':'{',']':'[',')':'('} # 字典中的键值对为正确括号匹配 for i in str: if i in {'(','[','{'}: # 如果是左括号,则入栈 stack.push(i) else: # 右括号的三种情况 if stack.is_empty(): # 栈为空直接判断False return False elif stack.get_top() == match[i]: # 栈不为空时栈顶匹配字典,匹配上为一对则出栈 stack.pop() else: # 匹配不上判断False return False if stack.is_empty(): # 直到匹配所有字符后栈为空,则说明括号匹配成功 return True else: return False
4. 队列:先进先出
5. 环形队列:首尾相连的队列
6. 队列的实现
# 环形队列 class Queue: def __init__(self, size): self.queue = [None for _ in range(size)] self.size = size self.rear = 0 # 队尾指针 self.front = 0 # 队首指针 # 队尾队列 def push(self, ele): if not self.is_filled(): self.rear = (self.rear + 1) % self.size self.queue[self.rear] = ele else: raise IndexError("Queue is filled") # 队首指针 def pop(self): if not self.is_empty(): self.front = (self.front + 1) % self.size return self.queue[self.front] else: raise IndexError("Queue is empty") # 队空判断 def is_empty(self): return self.rear == self.front # 堆满判断 def is_filled(self): return (self.rear + 1) % self.size == self.front
7. 经典算法题,迷宫问题
1. 使用栈算法求迷宫问题: 深度优先搜索
# 栈思想 moze = [ [1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,1,1,1,0,0,0,0,1,0,1], [1,0,0,0,0,0,1,1,1,1,1,0,1], [1,0,1,1,1,1,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,1,1,0,1,1,1], [1,1,1,1,0,1,1,1,1,0,1,1,1], [1,1,0,0,0,0,0,0,0,0,1,1,1], [1,1,1,1,1,1,1,1,1,0,0,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1] ] # 封装四个方向的函数,将函数的返回值作为列表中的元素 dirs = [ lambda x, y: (x+1, y), lambda x, y: (x-1, y), lambda x, y: (x, y+1), lambda x, y: (x, y-1) ] def moze_path(x1,y1,x2,y2): # x1,y1为起始位置,x2,y2为终点位置 stack = [] # 建栈,栈看做一个列表 stack.append((x1,y1)) # 初始位置进栈 while(len(stack)>0): # 栈中有值继续走,没有值说明出栈到原点了,没有路走 curNode = stack[-1] # 取栈顶为当前的节点 # 当栈顶等于终点位置,则说明走到终点了 if curNode[0] == x2 and curNode[1] == y2: for i in stack: print(i) return True for dir in dirs: # 调用lambda函数,分别传入当前节点坐标值 nextNode = dir(curNode[0],curNode[1]) # 如果下一个节点能走,则进栈 if moze[nextNode[0]][nextNode[1]] == 0: stack.append(nextNode) # 将走过的位置进行标志,防止走回头路 moze[nextNode[0]][nextNode[1]] = 2 break else: maze[nextNode[0]][nextNode[1]] = 2 # 这里防止重走老路 stack.pop() else: return False
2. 使用队列算法求迷宫问题:广度优先搜索
# 队列思想 from collections import deque def moze_path_queue(x1,y1,x2,y2): queue = deque() # 创建队列 queue.append((x1,y1,-1)) # 队列为三维列表,最后元素为从某个元素进入队列的下标 path = [] # 存放出队的元素 # 当队列中存在元素时,说明存在路径 while len(queue)>0: curNode = queue.popleft() # 队尾出队 path.append(curNode) # 将出队的元素存起 # 到达终点后开始往前寻址 if curNode[0] == x2 and curNode[1] == y2: new_curNode = path[-1] # 初始值为出队列列表最后元素的位置 realPath = [] while new_curNode[2] != -1: # -1是最开始的位置,不等于-1的时候说明没到头 realPath.append(new_curNode[0:2]) # 存放位置坐标 new_curNode = path[new_curNode[2]] # new_curNode[2]为上一个过来点的下标 realPath.append(new_curNode[0:2]) realPath.reverse() for i in realPath: print(i) return True # 调用lambda函数,分别传入当前节点坐标值 for dir in dirs: nextNode = dir(curNode[0],curNode[1]) if moze[nextNode[0]][nextNode[1]] == 0: queue.append((nextNode[0],nextNode[1],len(path)-1)) moze[nextNode[0]][nextNode[1]] = 2 # 区别栈的就是没有break,会向所有符合的都进去,即广度优先搜索 else: return False