圖論(2)--最短路徑和最小生成樹
阿新 • • 發佈:2021-08-06
圖的最短路徑問題
問題描述
Matlab求解最短路徑
s = [9 9 1 1 2 2 2 7 7 6 6 5 5 4]; t = [1 7 7 2 8 3 5 8 6 8 5 3 4 3]; w = [4 8 3 8 2 7 4 1 6 6 2 14 10 9]; G = graph(s,t,w); plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2) set( gca, 'XTick', [], 'YTick', [] ); [P,d] = shortestpath(G, 9, 4) %注意:該函式matlab2015b之後才有哦 P裡面儲存的就是最短路徑上面的節點 % 在圖中高亮我們的最短路徑 myplot = plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2); %首先將圖賦給一個變數 highlight(myplot, P, 'EdgeColor', 'r') %對這個變數即我們剛剛繪製的圖形進行高亮處理(給邊加上r紅色) % 求出任意兩點的最短路徑矩陣 D = distances(G) %注意:該函式matlab2015b之後才有哦 D(1,2) % 1 -> 2的最短路徑 D(9,4) % 9 -> 4的最短路徑 % 找出給定範圍內的所有點 nearest(G,s,d) % 返回圖形 G 中與節點 s 的距離在 d 之內的所有節點 [nodeIDs,dist] = nearest(G, 2, 10) %注意:該函式matlab2016a之後才有哦
求最短路徑演算法
求解最短路徑演算法主要包括迪傑斯特拉演算法和弗洛伊德演算法
強烈推薦觀看視訊:圖論最短距離(Shortest Path)演算法動畫演示-Dijkstra(迪傑斯特拉)和Floyd(弗洛伊德)_嗶哩嗶哩_bilibili
迪傑斯特拉演算法的matlab實現
function [mydistance,mypath]=mydijkstra(a,sb,db); %輸入:a——鄰接矩陣;a(i,j)——i到j之間的距離,可以是有向的 %sb——起點的標號,db——終點的標號 %輸出:mydistance——最短路的距離,mypath——最短路的路徑 n=size(a,1);visited(1:0)=0; distance(1:n)=inf;distance(sb)=0; %起點到各頂點距離的初始化 visited(sb)=1;u=sb; %u為最新的S集合頂點 parent(1:0)=0; %前驅頂點的初始化 for i=1:n-1 id=find(visited==0); %查詢V-S集合的頂點 for v=id if a(u,v)+distance(u)<distance(v) distance(v)=distance(u)+a(u,v); %修改標號值 parent(v)=u; end end temp=distance; temp(visited==1)=inf; %已標號點的距離換成無窮大 [t,u]=min(temp); %找標號值最小的頂點 visited(u)=1; %標記已經標號的頂點 end mypath=[]; if parent(db)~=0 %如果存在路! t=db;mypath=[db]; while t~=sb P=parent(t); mypath=[P mypath]; t=P; end end mydistance=distance(db);
弗洛伊德演算法的matlab實現
function [dist,path]=myfloyd(a) %尋找i,j兩點最短路徑 % 輸入:a—鄰接矩陣,元素(aij)是頂點i到j之間的直達距離,可以是有向的 % sb—起點的標號;db—終點的標號 % 輸出:dist—最短路的距離;% path—最短路的路徑 n=size(a,1); m=a; for i=1:n %path矩陣的初始化 for j=1:n path(i,j)=j; end end for k=1:n for i=1:n for j=1:n if a(i,j)>a(i,k)+a(k,j) a(i,j)=a(i,k)+a(k,j); path(i,j)=k; end end end end for sb=1:n for db=1:n t=path(sb,db); dist(sb,db)=m(sb,t); while t~=db p=path(t,db); dist(sb,db)=dist(sb,db)+m(t,db); t=p; end end end
最小生成樹
連通賦權圖的具有最小權的生成樹叫做最小生成樹
問題描述
求解最小生成樹的演算法有Kruskal(克魯斯卡爾)和Prim(普里姆)演算法:
觀看視訊:最小生成樹(Kruskal(克魯斯卡爾)和Prim(普里姆))演算法動畫演示_嗶哩嗶哩_bilibili
Kruskal演算法matlab實現
%邊權矩陣,每一列都表示一條邊,從上到下分別為兩個頂點以及它們邊的權值
b = [1 1 1 2 2 3 3 4;
2 4 5 3 5 4 5 5;
8 1 5 6 7 9 10 3];
%sortrows函式對某一列進行比較排序,所以我們先轉置b矩陣,然後對第三列也就是權值進行排序
[B,i]=sortrows(b',3);
%再將其轉置回來
B=B';
%m為邊的條數,n為點的個數
m=size(b,2);n=5;
%t陣列用來標記選中的邊,k用來計數,T矩陣用來儲存選中的邊,c計算最小生成樹的總長度
t=1:n;k=0;T=[];c=0;
for i=1:m
if t(B(1,i))~=t(B(2,i))
k=k+1;T(k,1:2)=B(1:2,i),c=c+B(3,i);
tmin=min(t(B(1,i)),t(B(2,i)));
tmax=max(t(B(1,i)),t(B(2,i)));
for j=1:n
if t(j)==tmax
t(j)=tmin;
end
end
end
if k==n-1
break;
end
end
T,c,
來源:【MATLAB】最小生成樹Kruskal演算法_taoxing-CSDN部落格_kruskal演算法
Prim演算法matlab實現
function [result]=myprim(a)//a為傳入的每個點的距離矩陣
result=[];//用result(3×n)矩陣來表示,第一行表示起點,第二行表示終點,第三行表示權值
p=1;tb=2:length(a);
while size(result,2)~=length(a)-1
temp=a(p,tb);temp=temp(:);
d=min(temp);
[jb,kb]=find(a(p,tb) == d,1);
j=p(jb);k=tb(kb);
result=[result,[j;k;d]];p=[p,k];tb(find(tb==k))=[];
end
result第一行表示起點,第二行表示終點,第三行表示權值
來源:數模:最小生成樹prim演算法(通用matlab程式碼)_萌新的部落格-CSDN部落格_prim演算法matlab程式碼