目录
数据结构介绍
列表
栈
栈的基本操作:
栈的实现(使用一般列表结构即可实现):
栈的应用——括号匹配问题
队列
队列的实现方式——环形队列
队列的实现方式——双向队列
队列内置模块
栈和队列应用——迷宫问题
栈——深度优先搜索
队列——广度优先搜索
介绍:
分类:
列表与其他编程语言的数组有区别:1、数组元素类型相同;2、数组长度固定。
列表:是一种基本数据类型。
操作:
class Stack:
def __init__(self):
self.stack = []
# 进栈
def push(self, element):
self.stack.append(element)
# 出栈
def pop(self):
return self.stack.pop()
# 取栈顶
def get_top(self):
if len(self.stack) > 0:
return self.stack[-1]
else:
return None
# 举例
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop())
给一个字符串,其中包含小括号、中括号、大括号,求该字符串中的括号是否匹配。
例如:()()[]{} 匹配、([{()}]) 匹配、[]( 不匹配、[(]) 不匹配
class Stack:
def __init__(self):
self.stack = []
# 进栈
def push(self, element):
self.stack.append(element)
# 出栈
def pop(self):
return self.stack.pop()
# 取栈顶
def get_top(self):
if len(self.stack) > 0:
return self.stack[-1]
else:
return None
# 判断栈是否为空
def is_empty(self):
return len(self.stack) == 0
def brace_match(s):
stack = Stack()
match = {'}':'{', ']':'[', ')':'('}
for ch in s:
if ch in {'(', '[', '{'}:
stack.push(ch)
else:
if stack.is_empty():
return False
elif stack.get_top() == match[ch]:
stack.pop()
else: # stack.get_top() != match[ch]
return False
if stack.is_empty():
return True
else:
return False
print(brace_match("{(){}}{{}{}}"))
环形队列:当队尾指针front = Maxsize - 1时,再前进一个位置就自动到0
class Queue:
def __init__(self, size = 100): # 固定队列的长度(做环形队列)
self.queue = [0 for _ in range(size)]
self.size = size
self.rear = 0 # 队尾指针(入队)
self.front = 0 # 队首指针(出队)
# 入队
def push(self, element):
if not self.is_filled():
self.rear = (self.rear + 1) % self.size
self.queue[self.rear] = element
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
q = Queue(6)
for i in range(5):
q.push(i)
print(q.is_filled())
print(q.pop())
q.push(4)
双向队列:两端都支持进队和出队操作
双向队列基本操作:
使用方法:from collections impport deque
创建队列:queue = deque()
进队:append()
出队:popleft()
双向队列队首进队:appendleft()
双向队列队尾出队:pop()
# 双向队列
from collections import deque
# 创建队列
q = deque([1, 2, 3, 4, 5], 5) # 里面的第一个参数为列表,为队列初始化;第二个参数为int,是队列的长度
# 当队列满了之后继续入队,队首位置会向后一位,
q.append(1) # 队尾入队
q.popleft() # 队首出队
# 用于双向队列
q.appendleft() # 队首入队
q.pop() # 队尾出队
问题介绍:给一个二维列表,表示迷宫(0表示通道,1表示围墙);给出算法,求一条走出迷宫的路径。
maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 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 maze_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 p in stack:
print(p)
return True
# 上下左右四个方向搜索:上(x-1, y), 下(x+1, y), 左(x, y+1), 右(x, y-1)
for dir in dirs:
nextNode = dir(curNode[0], curNode[1])
# 如果下一个节点可以走
if maze[nextNode[0]][nextNode[1]] == 0:
stack.append(nextNode) # 如果可以走,就将该点压入栈
maze[nextNode[0]][nextNode[1]] = 2 # 然后将该点标记成2,2表示路以及走过
break # 找到一个就break,往下走
else: # 找不到就回退
maze[nextNode[0]][nextNode[1]] = 2
stack.pop() # 回退
else: # 栈空,未找到路
print("没有路")
return False
maze_path(1, 1, 8, 8)
可以计算最短路径
from collections import deque
maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 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 print_r(path):
curNode = path[-1]
realpath = []
while curNode[2] != -1:
realpath.append(curNode[0:2])
curNode = path[curNode[2]]
realpath.append(curNode[0:2]) # 最后将起点放进去
realpath.reverse()
for node in realpath:
print(node)
# 广度优先搜索
def maze_path_queue(x1, y1, x2, y2):
queue = deque() # 创建队列
queue.append((x1, y1, -1)) # 先将起点存储
path = []
while len(queue) > 0: # 队空表示无路
curNode = queue.pop()
path.append(curNode)
if curNode[0] == x2 and curNode[1] == y2:
# 终点
print_r(path)
return True
for dir in dirs:
nextNode = dir(curNode[0], curNode[1])
if maze[nextNode[0]][nextNode[1]] == 0:
queue.append((nextNode[0], nextNode[1], len(path)-1)) # 后续节点进队,记录从哪个节点过来
maze[nextNode[0]][nextNode[1]] = 2 # 标记为已经走过
else:
print("没有路")
return False
maze_path_queue(1, 1, 8, 8)
代码自己手动敲一遍理解更深哦!