最優路徑算法合集(附python源碼)(原創)
主要的最優(最短)路徑算法:
一、深度優先算法;二、廣度優先算法;三、Dijstra最短路徑;四、floyd最短路徑(待);
一、深度優先算法
圖的深度優先搜索(Depth First Search),和樹的先序遍歷比較類似。
它的思想:假設初始狀態是圖中所有頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點,然後依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中所有和v有路徑相通的頂點都被訪問到。 若此時尚有其他頂點未被訪問到,則另選一個未被訪問的頂點作起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。
無向無權值網絡
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: #View Code如果該路徑可行,則直接判斷 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)
輸入(無向圖):
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]]
輸出:
[‘A‘, ‘C‘, ‘B‘, ‘D‘, ‘F‘, ‘G‘, ‘E‘]
二、廣度優先算法
廣度優先搜索算法(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)View Code
輸入(有向圖):
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‘]
三、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)View Code
輸入:
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‘]
四、floyd最短路徑
!!!還沒看這個算法!!!
最優路徑算法合集(附python源碼)(原創)