深度优先算法:先纵向再横向,即从左到右,逐列遍历
广度优先算法:先横向再纵向,即从上到下,逐行遍历
这两个算法可用于不同的场景,就会有不同的结果和效率
它们的特点用形象点儿的比喻,深度优先像是执着耐心的渔翁,用一根鱼竿钓鱼,从一而终、专心致志,直到钓到鱼为止,感人肺腑,无论大鱼小鱼,钓到就够了。
但广度优先则像是个海王,普遍撒网重点捞鱼,脚踏多条船,像是拥有分身的八爪鱼,当探寻到大鱼,就会收手。
这两种算法,在不同的需求下,各有优劣,拿迷宫作为例子分析
- 假设用在经典的迷宫场景,首先,如果是传统意义的迷宫游戏,不存在唯一解,即只有一条路通往出口,那么深度优先和广度优先都是可以的。
- 但如果这个迷宫不存在唯一解,即有多条路通往出口,那么深度优先算法则无法完成,通常会选用广度优先。
# 栈——深度优先、队列——广度优先
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,1,0,1,1,0,0,1],
[1,0,1,1,1,0,0,0,0,1],
[1,0,0,1,0,1,0,0,0,1],
[1,0,1,0,0,0,1,0,0,1],
[1,0,0,1,1,1,1,1,0,1],
[1,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1],
]
maze1 = maze
dirs = [
lambda x,y:(x-1,y),
lambda x,y:(x,y-1),
lambda x,y:(x+1,y),
lambda x,y:(x,y+1)
]
def deep_maze():
start_pos = (1,1)
end_pos = (8,8)
stack = [start_pos]
while len(stack):
curnode = stack[-1]
if curnode[0] == end_pos[0] and curnode[1] == end_pos[1]:
print("深度优先路径:")
break
for pos in dirs:
nextnode = pos(curnode[0],curnode[1])
if maze1[nextnode[0]][nextnode[1]] == 0:
stack.append(nextnode)
maze1[nextnode[0]][nextnode[1]] = 2
break
else:
stack.pop()
if len(stack):
print(stack)
else:
print("死路一条,无路可走")
# 队列——广度优先
from collections import deque
maze2 = maze
def print_r(path):
index = len(path)-1
bestpath = []
bestpath.append((path[index][0],path[index][1]))
while index!=0:
index = path[index][2]
bestpath.append((path[index][0],path[index][1]))
for path in reversed(bestpath):
print(path)
def broad_maze():
start_pos = (1,1)
end_pos = (8,8)
path = []
queue = deque()
queue.append((1,1,-1))
while len(queue)>0:
curnode = queue.popleft()
path.append(curnode)
if curnode[0] == end_pos[0] and curnode[1] == end_pos[1]:
print(path)
print_r(path)
break
for pos in dirs:
nextnode = pos(curnode[0],curnode[1])
if maze2[nextnode[0]][nextnode[1]] == 0:
queue.append((nextnode[0],nextnode[1],path.index(curnode)))
maze2[nextnode[0]][nextnode[1]] = 2
else:
print("无路可走")
# deep_maze()
broad_maze()