主要的最優(最短)路徑算法:node
1、深度優先算法;2、廣度優先算法;3、Dijstra最短路徑;4、floyd最短路徑(待);算法
1、深度優先算法網絡
圖的深度優先搜索(Depth First Search),和樹的先序遍歷比較相似。app
它的思想:假設初始狀態是圖中全部頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點,而後依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中全部和v有路徑相通的頂點都被訪問到。 若此時尚有其餘頂點未被訪問到,則另選一個未被訪問的頂點做起始點,重複上述過程,直至圖中全部頂點都被訪問到爲止。ide
無向無權值網絡spa
data = [[0, 0, 1, 1, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 1, 1, 0]]
1 def depth_first_search(data, data_index): # 有向、無向均可以知足要求 2 d1 = [data_index[0]] 3 index_now = 0 4 5 for i in range(len(data_index) - 1): # 只須要再尋找剩餘的數值便可 6 state = 1 7 for j in range(len(data[index_now])): # 遍歷可行路徑 8 if data[index_now][j] == 1: # 若是該路徑可行,則直接判斷 9 if data_index[j] not in d1: # 判斷原始輸出中是否已有 10 d1.append(data_index[j])# 無,則加入 11 index_now = j 12 state = 0 13 break 14 if state: 15 for k in d1[-2::-1]: # 到達葉子後的操做 16 index_now = data_index.index(k) 17 for j in range(len(data[index_now])): # 遍歷可行路徑 18 if data[index_now][j] == 1: # 若是該路徑可行,則直接判斷 19 if data_index[j] not in d1: # 判斷原始輸出中是否已有 20 d1.append(data_index[j]) # 無,則加入 21 index_now = j 22 break 23 if index_now != data_index.index(k): 24 break 25 26 # print(d1) 27 return d1 28 29 if __name__ == "__main__": 30 data = [[0, 0, 1, 1, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0], 31 [0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 1, 1, 0]] 32 data_w = [[0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0], 33 [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0]] 34 data_index = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] 35 # print(data_index.index('F')) 36 d1 = depth_first_search(data_w, data_index) 37 print(d1)
輸入(無向圖):3d
data = [[0, 0, 1, 1, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 1, 1, 0]]
輸出:code
['A', 'C', 'B', 'D', 'F', 'G', 'E']視頻
2、廣度優先算法blog
廣度優先搜索算法(Breadth First Search),又稱爲"寬度優先搜索"或"橫向優先搜索",簡稱BFS。
它的思想是:從圖中某頂點v出發,在訪問了v以後依次訪問v的各個不曾訪問過的鄰接點,而後分別從這些鄰接點出發依次訪問它們的鄰接點,並使得「先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點被訪問,直至圖中全部已被訪問的頂點的鄰接點都被訪問到。若是此時圖中尚有頂點未被訪問,則須要另選一個不曾被訪問過的頂點做爲新的起始點,重複上述過程,直至圖中全部頂點都被訪問到爲止。
換句話說,廣度優先搜索遍歷圖的過程是以v爲起點,由近至遠,依次訪問和v有路徑相通且路徑長度爲1,2...的頂點。
1 def breadth_first_search(data, data_index): # 無向圖、有向圖均可以的 2 d1 = [data_index[0]] 3 index_now = [0] 4 while len(d1) != len(data_index): 5 index_mid = [] 6 for i in index_now: # i 爲當前 父節點 7 for j in range(len(data[i])): # 查詢父節點的子節點 8 if data[i][j] == 1: 9 if data_index[j] not in d1: 10 d1.append(data_index[j]) 11 index_mid.append(j) 12 index_now = index_mid 13 print(d1) 14 return d1 15 16 17 if __name__ == "__main__": 18 data = [[0, 0, 1, 1, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0], 19 [0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 1, 1, 0]] 20 data_w = [[0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0], 21 [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0]] 22 data_index = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] 23 # print(data_index.index('F')) 24 d1 = breadth_first_search(data_w, data_index) 25 # print(d1)
輸入(有向圖):
data_w = [[0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0]]
輸出:
['A', 'B', 'C', 'E', 'F', 'D', 'G']
3、Dijstra最短路徑(迪傑斯特拉算法)
參考視頻:https://www.bilibili.com/video/av25829980?from=search&seid=7854146334299589449
迪傑斯特拉算法是由荷蘭計算機科學家狄克斯特拉於1959 年提出的,所以又叫狄克斯特拉算法。是從一個頂點到其他各頂點的最短路徑算法,解決的是有向圖中最短路徑問題。迪傑斯特拉算法主要特色是以起始點爲中心向外層層擴展,直到擴展到終點爲止。
OSPF協議 :Open Shortest Path First開放式最短路徑優先,底層是迪傑斯特拉算法,是鏈路狀態路由選擇協議,它選擇路由的度量標準是帶寬,延遲。
1 def priority_queue(data, d0): # 自建優先隊列格式 2 state = 1 3 for i in range(len(data)): 4 if d0[1] < data[i][1]: 5 data.insert(i, d0) 6 state = 0 7 break 8 if state: 9 data.append(d0) 10 return data 11 12 13 def dijkstra_search(data, data_index, index): 14 parent = {} # 字典映射,更新前級節點 15 queue = [] # 優先隊列 16 queue_out = [[data_index[index], data[index][index], 0]] # 輸出隊列 17 18 while len(queue_out) < len(data_index): 19 root_node = data_index.index(queue_out[-1][0]) # 當前最優節點 20 # print(root_node) 21 for i in range(len(data_index)): # 遍歷全部的可能性 22 if data[root_node][i] != -1: # 檢查是否可直連,是 23 if data_index[i] not in [x[0] for x in queue_out]: 24 queue = priority_queue(queue, 25 [data_index[i], data[root_node][i] + queue_out[-1][1], queue_out[-1][0]]) 26 # print(queue) # 檢查優先隊列的狀況 [['C', 1], ['B', 5]] 27 28 for i in range(len(queue)): # 0,1 29 # print(queue[i][0]) 30 if queue[i][0] not in [x[0] for x in queue_out]: 31 parent[queue[i][0]] = queue[i][-1] 32 queue_out.append(queue[i]) 33 del queue[i] 34 break 35 36 # print(queue) 37 # print('queue_out',queue_out) 38 return queue_out, parent 39 40 41 if __name__ == "__main__": 42 43 data_weight = [[0, 5, 1, -1, -1, -1], [5, 0, 2, 1, -1, -1], [1, 2, 0, 4, 8, -1], [-1, 1, 4, 0, 3, 6], 44 [-1, -1, 8, 3, 0, -1], [-1, -1, -1, 6, -1, -1]] 45 data_index = ['A', 'B', 'C', 'D', 'E', 'F'] 46 # print(data_index.index('F')) 47 d1, d2 = dijkstra_search(data_weight, data_index, 3) 48 print(d1) 49 print(d2) 50 51 target = 'A' 52 for i in d1: 53 if i[0] == target: 54 print('路徑最短距離爲:', i[1]) 55 56 key = target 57 d3 = [target] 58 while key in d2.keys(): 59 d3.insert(0, d2[key]) 60 key = d2[key] 61 print('最優路線爲:', d3)
輸入:
data_weight = [[0, 5, 1, -1, -1, -1], [5, 0, 2, 1, -1, -1], [1, 2, 0, 4, 8, -1], [-1, 1, 4, 0, 3, 6], [-1, -1, 8, 3, 0, -1], [-1, -1, -1, 6, -1, -1]]
data_index = ['A', 'B', 'C', 'D', 'E', 'F']
d1, d2 = dijkstra_search(data_weight, data_index, 0)
輸出:
路徑最短距離爲: 10
最優路線爲: ['A', 'C', 'B', 'D', 'F']
4、floyd最短路徑
!!!還沒看這個算法!!!