日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

图论基础知识--最小生成树算法kruskal(克鲁斯克尔)和普里姆算法(Prim算法);最短路径算法Dijkstra(迪杰斯特拉)和Floyd(弗洛伊德)

發(fā)布時(shí)間:2024/7/23 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图论基础知识--最小生成树算法kruskal(克鲁斯克尔)和普里姆算法(Prim算法);最短路径算法Dijkstra(迪杰斯特拉)和Floyd(弗洛伊德) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一.基礎(chǔ)知識(shí)

?

? ? ? ? ?有向圖? ?無(wú)向圖

以無(wú)向圖為例:

鄰接矩陣:

度矩陣(對(duì)角矩陣):

二.最小生成樹

應(yīng)用:將網(wǎng)絡(luò)頂點(diǎn)看著城市,邊看著城市之間通訊網(wǎng),邊的權(quán)重看著成本,根據(jù)最小生成樹可以構(gòu)建城市之間成本最低的通訊網(wǎng).

1.kruskal(克魯斯克爾)算法

2.普里姆算法(Prim算法)

求點(diǎn)與點(diǎn)之間的最小生成樹

代碼:

#coding:utf-8 """ 最小生成樹 """ import networkx as nx import matplotlib.pyplot as plt import numpy as np from numpy import randomG = nx.Graph() # Matrix = np.array(random.randint((5), size=(5, 5))) # print('==Matrix:', Matrix) # print(maps) Matrix = np.array( [[3, 4, 0, 2, 2],[4, 1, 0, 3, 4],[0, 0, 0, 4, 4],[2, 3, 4, 0, 3],[2, 4, 4, 3, 1]]) #實(shí)際在用的時(shí)候,只用了下三角矩陣 #構(gòu)建無(wú)向圖 for i in range(len(Matrix)):for j in range(len(Matrix)):if Matrix[i, j] != 0:G.add_edge(i, j) nx.draw_networkx(G) plt.title("G") plt.show()class Graph(object):def __init__(self, Matrix):self.Matrix = Matrixself.nodenum = self.get_nodenum()self.edgenum = self.get_edgenum()def get_nodenum(self):return len(self.Matrix)def get_edgenum(self):count = 0for i in range(self.nodenum): # 獲取除去對(duì)角的下三角矩陣for j in range(i):# print('i,j', i, j)if self.Matrix[i][j] > 0 and self.Matrix[i][j] < 9999:count += 1return countdef kruskal(self):list = []if self.nodenum <= 0 or self.edgenum < self.nodenum - 1:return listedge_list = []for i in range(self.nodenum): # 獲取除去對(duì)角的下三角矩陣for j in range(i):if self.Matrix[i][j] < 9999:edge_list.append([i, j, self.Matrix[i][j]])print('==排序之前邊的集合 edge_list:', edge_list)edge_list.sort(key=lambda a: a[2]) # 已經(jīng)排好序的邊集合print('==排序以后邊的集合 edge_list:', edge_list)group = [[i] for i in range(self.nodenum)] # 存儲(chǔ)代表元列表print('存儲(chǔ)代表元列表', group)for edge in edge_list:for i in range(len(group)):if edge[0] in group[i]:m = i#開始節(jié)點(diǎn)if edge[1] in group[i]:n = i#終止節(jié)點(diǎn)if m != n:# 合并聯(lián)通分量 進(jìn)行存儲(chǔ)元列表更新list.append(edge)print('開始節(jié)點(diǎn)m,終止節(jié)點(diǎn)n:', m, n)group[m] = group[m] + group[n]group[n] = []print('==更新后的代表元列表:', group)return listdef prim(self):list = []if self.nodenum <= 0 or self.edgenum < self.nodenum - 1:return listselected_node = [0]candidate_node = [i for i in range(1, self.nodenum)]#候選節(jié)點(diǎn)# print('==candidate_node:', candidate_node)while len(candidate_node) > 0:begin, end, minweight = 0, 0, 9999for i in selected_node:for j in candidate_node:if self.Matrix[i][j] < minweight:minweight = self.Matrix[i][j]begin = i#存儲(chǔ)開始節(jié)點(diǎn)end = j#存儲(chǔ)終止節(jié)點(diǎn)list.append([begin, end, minweight])selected_node.append(end)#找到權(quán)重最小的邊 加入可選節(jié)點(diǎn)candidate_node.remove(end)#候選節(jié)點(diǎn)被找到 進(jìn)行移除return list # # G = Graph(Matrix) print('鄰接矩陣為\n%s' % G.Matrix) print('節(jié)點(diǎn)數(shù)據(jù)為%d,邊數(shù)為%d\n' % (G.nodenum, G.edgenum)) print('------最小生成樹kruskal算法------') print(G.kruskal())print('------最小生成樹prim算法') print(G.prim())

?

三.最短路徑:

1.Dijkstra(迪杰斯特拉)算法

Dijkstra算法用于解決單源最短路問(wèn)題,所謂單源最短路就是指定一個(gè)起點(diǎn),求出這個(gè)起點(diǎn)到其它所有點(diǎn)的最短路。本質(zhì)就是依次讓每個(gè)頂點(diǎn)作為起點(diǎn),更新最短路的過(guò)程。

示例:求M到各個(gè)頂點(diǎn)的最短路徑

? ? ? ? ? ? ?

先構(gòu)建鄰接矩陣Adjacent, 初始狀態(tài)dist[1~n] = inf, dist[M]=0,頂點(diǎn)更新狀態(tài)vst[1~n] = 0

以點(diǎn)M為起點(diǎn):

dist[M] = 0 vst[M] = 0 dist[W] = inf vst[W] = 0 dist[E] = inf vst[E] = 0 dist[D] = inf vst[D] = 0 dist[X] = inf vst[X] = 0

找出dist中值最小且未被使用的點(diǎn),發(fā)現(xiàn)dist[M]=0最小,且vst[M]=0,未被使用,故將M作為新的起點(diǎn).
找出所有M可達(dá)的頂點(diǎn),為X、W、E
dist[X]=inf > 0+10 ,更新dist[X]=10
dist[W]=inf > 0+5 ,更新dist[W]=5
dist[E]=inf > 0+8 ,更新dist[E]=8
M已被使用,vst[M]=1

dist[M] = 0 vst[M] = 1 dist[W] = 5 vst[W] = 0 dist[E] = 8 vst[E] = 0 dist[D] = inf vst[D] = 0 dist[X] = 10 vst[X] = 0

依次遍歷每個(gè)頂點(diǎn)........?

Inf = float('inf') # Dijkstra算法,就是依次讓每個(gè)頂點(diǎn)作為起點(diǎn),更新最短路的過(guò)程。 Adjacent = [[0, 10, 5, Inf, 8],[10, 0, 3, 1, Inf],[5, 3, 0, 9, 2],[Inf, 1, 9, 0, 6],[8, Inf, 2, 6, 0]]Src, Dst, N = 0, 4, 5def dijstra(adj, src, dst, n):dist = [Inf] * n # 初始化為inf無(wú)窮大dist[src] = 0 # 起始點(diǎn)到起始點(diǎn)距離為0vst = [0] * n # 記錄已經(jīng)確定的頂點(diǎn)prev = [0] * nwhile True:now = -1for u in range(n): # 找到dist最小且vst=0的點(diǎn)作為起點(diǎn)if not vst[u] and (now == -1 or dist[u] < dist[now]):now = uprint('====now:', now)if now == -1: # now未被更新,即表示所有頂點(diǎn)都被使用過(guò),算法結(jié)束breakfor v in range(n): # 遍歷當(dāng)前起點(diǎn)now能到達(dá)的所有點(diǎn)if dist[v] > dist[now] + adj[now][v]: # 如果dist[v]大于dist[now] + adj[now][v] 則更新dist[v] = dist[now] + adj[now][v]prev[v] = nowprint('==dist:', dist)# assert 1==0vst[now] = 1 # 當(dāng)前起點(diǎn)now已被使用過(guò),vst[now]=1# print('===dist:', dist)# print('==prev:', prev)## print('==dist[dst]:', dist[dst])return dist, prevdist, prev = dijstra(Adjacent, Src, Dst, N)print('==dist,prev:', dist, prev)def construct_path(prev, index, path=[]):path = path + [prev[index]]if prev[index] == 0:#終止條件return pathnew_path = construct_path(prev, prev[index], path)return new_path # res = construct_path(prev, 4,[4]) # print('==res:', res) for i in range(len(prev)):path = construct_path(prev, i, [i])print('{}節(jié)點(diǎn)路徑為:{}'.format(i, path))

2.Floyd(弗洛伊德)

本質(zhì)任意兩個(gè)節(jié)點(diǎn)最短路徑是否經(jīng)過(guò)此節(jié)點(diǎn),用dp的思想來(lái)存儲(chǔ)中間結(jié)果.

示例:

#Floyd(弗洛伊德)找最短路徑 本質(zhì)任意兩個(gè)節(jié)點(diǎn)最短路徑是否經(jīng)過(guò)此節(jié)點(diǎn) import numpy as np Inf = float('inf') DIS = [[0, 3, 8, Inf, -4],[Inf, 0, Inf, 1, 7],[Inf, 4, 0, Inf, Inf],[2, Inf, -5, 0, Inf],[Inf, Inf, Inf, 6, 0]]Direction = [[0, 1, 2, 3, 4],[0, 1, 2, 3, 4],[0, 1, 2, 3, 4],[0, 1, 2, 3, 4],[0, 1, 2, 3, 4]] V = 5 #k就是是否要經(jīng)過(guò)的節(jié)點(diǎn),i就是開始節(jié)點(diǎn),j就是終止節(jié)點(diǎn) for k in range(V):for i in range(V):for j in range(V):if DIS[i][k] + DIS[k][j] < DIS[i][j]:DIS[i][j] = DIS[i][k] + DIS[k][j]Direction[i][j] = Direction[i][k]print('最終的距離矩陣{}'.format(np.array(DIS))) print('方向矩陣{}'.format(np.array(Direction)))def construct_path(Direction, i, j, path=[]):path = path + [Direction[i][j]]if Direction[i][j] == j:#終止條件return pathnew_path = construct_path(Direction, Direction[i][j], j, path)return new_path#找到路徑 for i in range(V):for j in range(V):path = construct_path(Direction, i, j, [i])print('{}--{}節(jié)點(diǎn)路徑為:{}'.format(i, j, path))

?最終的距離矩陣和方向矩陣,其中方向矩陣可以用來(lái)還原開始節(jié)點(diǎn)到終止節(jié)點(diǎn)的路徑:

參考:

https://blog.csdn.net/weixin_43093481/article/details/82702176

https://www.bilibili.com/video/BV1q4411M7r9?from=search&seid=4042347737055062965

總結(jié)

以上是生活随笔為你收集整理的图论基础知识--最小生成树算法kruskal(克鲁斯克尔)和普里姆算法(Prim算法);最短路径算法Dijkstra(迪杰斯特拉)和Floyd(弗洛伊德)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。