廣度優先搜索——狄克斯特拉算法python個例展示

1. 狄克斯特拉算法介紹

適用條件:
1.只適用於有向無環圖(無向圖每條邊都是環)
2.繞環的路徑不可能是最短路徑
3.計算加權圖時用此算法
4. 不支持負權重

計算步驟:
1.找出最短時間內到達的節點
2.若找到更短路徑,則更新到達該節點的鄰居時間
3.重複此過程,直到對每個節點都做過
4.計算最終路徑
在這裏插入圖片描述
如上圖,起點記作start,終點記作 fin,中間節點記作a,b,c,d。權重如邊上數字所示。
目標:找出start到fin的最短路徑(包括權重),並計算最短距離是多少。

#創建散列表來儲存鄰居及其權重
graph={}
graph['start']={}
graph['start']['a']=5
graph['start']['b']=2

graph['a']={}
graph['a']['c']=4
graph['a']['d']=2

graph['b']={}
graph['b']['a']=8
graph['b']['d']=7

graph['c']={}
graph['c']['fin']=3
graph['c']['d']=6

graph['d']={}
graph['d']['fin']=1

graph['fin']={}
##創建開銷表,只創建從start到鄰近節點的costs,其餘節點設置爲inf,並通過後續的迭代進行更新
infinity=float('inf')
costs={}
costs['a']=5
costs['b']=2
costs['c']=infinity
costs['d']=infinity
costs['fin']=infinity
##創建一個存儲父節點的散列表,只存儲start臨近點的父節點記錄,其他的節點父節點暫且
##設置爲None,通過後續的迭代進行更新
parents={}
parents['a']='start'
parents['b']='start'
parents['c']=None
parents['d']=None
parents['fin']=None

記錄結果如下,接下來就是要不斷的更新相應節點的costs和parents
在這裏插入圖片描述

def find_lowest_cost_node(costs):
    lowest_cost=float('inf')
    lowest_cost_node=None
    for node in costs:  #遍歷所有節點
        cost=costs[node]
        if cost< lowest_cost and node not in processed:  #如果當前的節點的開銷
                                                                             #更低且未處理過
            lowest_cost=cost                         #就將其視爲開銷最低的節點
            lowest_cost_node=node
            
    return lowest_cost_node
processed=[]  #記錄已經處理過的節點

node=find_lowest_cost_node(costs)  #在未處理的節點中找出開銷最小的節點

while node is not None:  #這個wile循環在所有節點都被處理過後結束
    cost=costs[node]
    neighbors=graph[node]
    for n in neighbors.keys(): #遍歷當前節點的所有鄰居
        new_cost=cost+neighbors[n]
        if costs[n]> new_cost:  #如果經當前節點前往該鄰居更近
            costs[n]=new_cost    #就更新該鄰居的開銷
            parents[n]=node     #同時將該鄰居的父節點設置爲當前節點
    processed.append(node)     #將當前節點標記爲處理過
    node=find_lowest_cost_node(costs)  #找出接下來要處理的節點,並循環

全部跑完之後的結果如下:
在這裏插入圖片描述
可以到看,從起點start到終點fin的最短距離爲8,路徑爲:fin-d-a-start.(由父親節點指向可知)

總結:

  1. 廣度優先搜索用於在非加權圖中查找最短路徑;
  2. 狄克斯特拉算法算法用於在加權圖中查找最短路徑;
  3. 僅當權重爲正時狄克斯特拉算法才管用;
  4. 如果圖中包含負權邊,請使用貝爾曼-福德算法;

2. 廣度優先搜索介紹

使用隊列(先進先出):
在這裏插入圖片描述
如圖,找出距離中間you(你)最近的符合某個特徵的人,比如,名字長度爲4(爲芒果銷售商)

##廣度優先搜素
graph={}
graph['you']=['alice','bob','claire'] 
graph['alice']=['peggy']
graph['bob']=['anuj','peggy']
graph['claire']=['thom','jonny']
graph['anuj']=[]
graph['peggy']=[]
graph['thom']=[]
graph['jonny']=[]
from collections import deque

#search_queue = deque() #創建一個隊列
#search_queue += graph['you']  #將你的鄰居都加入到這個搜索隊列中

def person_is_seller(name):
    return len(name)==4

def search(name):
    
    search_queue=deque() #創建一個隊列
    search_queue += graph[name]  #將name的鄰居都加入到這個搜索隊列中
    searched=[]
    
    while search_queue:  #只要隊列不空
        person=search_queue.popleft() #就取出其中的第一個人
        if person not in searched:   #僅當這個人沒有檢查過時才檢查
            if person_is_seller(person):  
                print(person+" is a mango seller")
                return True   
            else:
                search_queue += graph[person]   #不符合特徵,將這個人的朋友都加入搜索隊列
                searched.append(person)  #將這個人標記爲檢查過
    return False  #如果到了這裏,就說明隊列中沒人是符合特徵

總結:

  1. 廣度優先搜索指出是否有從A到B的路徑
  2. 如果有,廣度優先搜索將找出最短路徑
  3. 面臨類似於尋找最短路徑的問題時,可嘗試使用圖來建立模型,再使用廣度優先搜索來解決問題。
  4. 隊列是先進先出的(FIFO),可以以queue排隊來記憶,排隊講究先來後到
  5. 棧是後進先出的(LIFO)的。
  6. 你需要按加入順序檢查搜索列表中的人,否則找到的就不是最短路徑,因此搜索列表必須是隊列;
  7. 對於檢查過的人,務必不要再去檢查,否則可能導致無限循環。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章