(原创)广度优先搜索解决最短路径问题
程序员文章站
2022-06-11 21:01:56
...
一、用途
广度优先搜索用于解决两种问题:
1.从某点到某点是否存在路径?
2.若存在,最短的是哪条?
二、简单介绍图
1.图有点和边组成。
2.当图中的所有边的指向都是单向的,这种图叫做有向图。若A指向B,则B为A的邻居。
3.当图中存在一条或一条以上的没有箭头的边,即A指向B,且B指向A,这种图成为无向图。其中,A和B互为邻居。
4.如下图,其中若从A出发,则B、C、D是一度关系,E、F是二度关系,以此类推。
三、简单介绍队列
1.队列只包括两种操作:入队与出队。
2.队列是一种先进先出的数据结构(First In First Out,FIFO);栈是一种后进先出的数据结构(Last In First Out,LIFO)。
四、广度优先算法实现逻辑
假设要在上图中寻找从A到E的最短路径:
1.将A的一度关系加入搜索队列。
2.判断搜索队列是否为空,是则返回False,表示不存在到E的路径,否则检查队列的第一个点。
2.检查该点是否被搜索过了,是则跳过。否则判断该点是否是E,是则返回true,否则将该点移除,并放入已经搜索过的点的列表,将该点的下一层加入整个待搜索队列的后面。
3.重复第二步。
注意!!
a.要将下一层放在队列的最后面,才能确保找到的是最短路径。
b.检查过的点要放入已经搜索过的队列,并在每次检查时判断该点是否在搜索过的队列里,防止重复搜索。否则当出现无向图时,会进入死循环。
五、运行时间
广度优先搜索的运行时间是:O(V+E)
解析:
广度优先遍历需要在整个图网中进行遍历,所以会遍历每一条边,所以至少运行时间是O(边数),即O(E),E为边数;
而每次遍历一个点,就需要将它的下一层添加到队列,在散列表中添加一个对象是常数时间O(1),所以运行时间还要加上O(节点数),即O(V),V是节点数。
所以最后的运行时间是:O(V) + O(E) = O(V+E)。
六、具体实现
"""
广度优先搜索
"""
dict = {}
dict["oysq"] = ["a", "b", "c"]
dict["a"] = ["e", "f", "g"]
dict["b"] = ["h", "i"]
dict["c"] = []
dict["d"] = []
dict["e"] = []
dict["f"] = []
dict["g"] = []
dict["h"] = ["j", "k"]
dict["i"] = []
dict["j"] = []
dict["k"] = ["l"]
dict["l"] = []
def search(dict, head, target):
search_list = []
search_list += dict[head]
searched = []
while search_list != []:
temp = search_list.pop()
if searched.count(temp) == 0:
if temp == target:
return True;
else:
search_list += dict[temp]
searched += temp
return False
print search(dict, "oysq", "c")
print search(dict, "oysq", "v")