DFS & BFS
简单介绍
DFS (depth first search) 和 BFS (breadth first search) 是两种比较基础的寻迹算法。何谓寻迹算法呢?限本人语言功底有限(高考语文不及格),不岔开来讲,请自行百度或谷歌。反正字面意思,就是找到路径的算法。
这是DFS跑的图,感觉走位很蛇皮。有点淡紫色的是寻迹走过的点,蓝色开始点,绿色是结束点。
这是BFS跑的,走位不这么蛇皮了, 算是直直的找到了目标点。
原理
DFS
首先申明一下,这里我假设寻迹只能从四个方向走,上下左右。
直接先PO一下DFS的伪代码
all nodes = {distance=infinity, parent=none, visited=False}
start_node = {distance=0, parent=none, visited=True}
visit_stack.append(start_node)
while iterate == True:
current_node = pop (visit_stack)
for each nodes_near_by:
if (test_collision(nodes_near_by)==false) && nodes_near_by.visited = False :
visit_stack.append(nodes_near_by)
if nodes_near_by.distance>current_node.distance + cal_distance(nodes_near_by, current_node):
nodes_near_by.parent = current_node
nodes_near_by.distance = current_node.distance + cal_distance(nodes_near_by, current_node)
if nodes_near_by == goal_node:
nodes_near_by.parent = current_node
iterate = False
break
nodes_near_by. visited = True
大致是这么个意思,来解释一下。
node 在这里中文意思是节点的意思。
这里visit_stack可以看作一个列表或者数组,里面存放着已经访问过的点。在循环的时候,会pop出current_node(pop在此解释一下是删掉数组里最后一个元素,并返回删除元素的值)。 test_collision 在这里表示检测是否与障碍物相碰撞,具体怎么检测按具体情况而定,在这里不岔开来讲。
nodes_near_by代表current_node周围的点,我做的是周围四个点,8个点讲道理也是可以的。
cal_distance 这个是计算两个点之间的距离,一般来说相邻点之间的距离就是定值。
整个程序的意思就是:先把所有点初始化,每个点有三个量(struct结构体搞一下哈),每个点初始的distance都为无限大。然后会有一个数据集,叫做visit_stack(列表或数组)。在寻迹前已知起始点(start_node),和目标点(goal_node)。第一步会把起始点放到visit_stack里, 然后进入循环。
每次循环先pop出来一个点当作current_node,然后再current_node 周围找点进行判断。如果nodes_near_by的distance量大于current_node的distance的量与cal_distance(nodes_near_by, current_node)之和,说明是一条路子,就把nodes_near_by的parent指为 current_node,nodes_near_by的distance也更新一下。当周围点就是目标点时,终止循环。
然后就可以从goal_node开始溯源,goal_node的爸爸是谁,goal_node的爸爸是谁,goal_node的爸爸的爸爸是谁,直到goal_node的爸爸的爸爸的爸爸。。。爸爸是start_node为止。然后这样路径就出来了(伪代码种没有包含)。
BFS
BFS的代码和DFS代码非常相像。
all nodes = {distance=infinity, parent=none, visited=False}
start_node = {distance=0, parent=none, visited=True}
visit_stack.append(start_node)
while iterate == True:
current_node = shift(visit_stack)
for each nodes_near_by:
if (test_collision(nodes_near_by)==false) && nodes_near_by.visited = False :
visit_stack.append(nodes_near_by)
if nodes_near_by.distance>current_node.distance + cal_distance(nodes_near_by, current_node):
nodes_near_by.parent = current_node
nodes_near_by.distance = current_node.distance + cal_distance(nodes_near_by, current_node)
if nodes_near_by == goal_node:
nodes_near_by.parent = current_node
iterate = False
break
nodes_near_by. visited = True
来来来,大家来找下不同。
大家的眼睛还是雪亮的。BFS 和 DFS唯一的区别就是就是在while循环里,一开始的pop变成了shift。
shift 和 pop 比,恰恰相反,是删掉数组里第一个元素,并返回删除元素的值。
看一下,这里 BFS 是像菱形一样向外扩张的。
总结
这两个算法算是比较简单的寻迹算法,BFS相对于DFS是可以找到比较优的路径的。后面我还会写A*寻迹算法,和这个比起来,BFS和DFS就是个弟弟,但其实三者框架大致一样。