當前位置:首頁 » 操作系統 » prim演算法求最小生成樹

prim演算法求最小生成樹

發布時間: 2023-01-06 16:27:43

『壹』 關於Prim演算法求最小生成樹的問題

PrimMST(G,T,r){ //求圖G的以r為根的MST,結果放在T=(U,TE)中 InitCandidateSet(…);//初始化:設置初始的輕邊候選集,並置T=({r},¢) for(k=0;k<n-1;k++){ //求T的n-1條樹邊 (u,v)=SelectLiShtEdge(…);//選取輕邊(u,v); T←T∪{(u,v)};//擴充T,即(u,v)塗紅加入TE,藍點v並人紅點集U ModifyCandidateSet(…); //根據新紅點v調整候選輕邊集 } }

『貳』 最小生成樹怎麼求

一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊。最小生成樹可以用kruskal(克魯斯卡爾)演算法或Prim(普里姆)演算法求出。

求MST的一般演算法可描述為:針對圖G,從空樹T開始,往集合T中逐條選擇並加入n-1條安全邊(u,v),最終生成一棵含n-1條邊的MST。
當一條邊(u,v)加入T時,必須保證T∪{(u,v)}仍是MST的子集,我們將這樣的邊稱為T的安全邊。
偽代碼

GenerieMST(G){//求G的某棵MST
T〈-¢; //T初始為空,是指頂點集和邊集均空
while T未形成G的生成樹 do{
找出T的一條安全邊(u,v);//即T∪{(u,v)}仍為MST的子集
T=T∪{(u,v)}; //加入安全邊,擴充T
}
return T; //T為生成樹且是G的一棵MST
}
注意:
下面給出的兩種求MST的演算法均是對上述的一般演算法的求精,兩演算法的區別僅在於求安全邊的方法不同。
為簡單起見,下面用序號0,1,…,n-1來表示頂點集,即是:
V(G)={0,1,…,n-1},
G中邊上的權解釋為長度,並設T=(U,TE)。
求最小生成樹的具體演算法(pascal):
Prim演算法

procere prim(v0:integer);
var
lowcost,closest:array[1..maxn] of integer;
i,j,k,min:integer;
begin
for i:=1 to n do begin
lowcost[i]:=cost[v0,i];
closest[i]:=v0;
end;
for i:=1 to n-1 do begin
{尋找離生成樹最近的未加入頂點 k}
min:=maxlongint;
for j:=1 to n do
if (lowcost[j]<min) and (lowcost[j]<>0) then begin
min:=lowcost[j];
k:=j;
end;
lowcost[k]:=0; {將頂點k 加入生成樹}
{生成樹中增加一條新的邊 k 到 closest[k]}
{修正各點的 lowcost 和 closest 值}
for j:=1 to n do
if cost[k,j]<lowcost[j] then begin
lowcost[j]:=cost[k,j];
closest[j]:=k;
end;
end;
end;
Kruskal演算法

按權值遞增順序刪去圖中的邊,若不形成迴路則將此邊加入最小生成樹。
function find(v:integer):integer; {返回頂點 v 所在的集合}
var i:integer;
begin
i:=1;
while (i<=n) and (not v in vset) do inc(i);
if i<=n then find:=i else find:=0;
end;
procere kruskal;
var
tot,i,j:integer;
begin
for i:=1 to n do vset:=i;{初始化定義 n 個集合,第 I個集合包含一個元素 I}
p:=n-1; q:=1; tot:=0; {p 為尚待加入的邊數,q 為邊集指針}
sort;
{對所有邊按權值遞增排序,存於 e中,e.v1 與 e.v2 為邊 I 所連接的兩個頂點的
序號,e.len 為第 I條邊的長度}
while p>0 do begin
i:=find(e[q].v1);j:=find(e[q].v2);
if i<>j then begin
inc(tot,e[q].len);
vset:=vset+vset[j];vset[j]:=[];
dec(p);
end;
inc(q);
end;
writeln(tot);
end;
c語言代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
#defineMAX_VERTEX_NUM20
#defineOK1
#defineERROR0
#defineMAX1000
typedefstructArcell
{
doubleadj;
}Arcell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{
charvexs[MAX_VERTEX_NUM];//節點數組
AdjMatrixarcs;//鄰接矩陣
intvexnum,arcnum;//圖的當前節點數和弧數
}MGraph;
typedefstructPnode//用於普利姆演算法
{
charadjvex;//節點
doublelowcost;//權值
}Pnode,Closedge[MAX_VERTEX_NUM];//記錄頂點集U到V-U的代價最小的邊的輔助數組定義
typedefstructKnode//用於克魯斯卡爾演算法中存儲一條邊及其對應的2個節點
{
charch1;//節點1
charch2;//節點2
doublevalue;//權值
}Knode,Dgevalue[MAX_VERTEX_NUM];

//-------------------------------------------------------------------------------
intCreateUDG(MGraph&G,Dgevalue&dgevalue);
intLocateVex(MGraphG,charch);
intMinimum(MGraphG,Closedgeclosedge);
voidMiniSpanTree_PRIM(MGraphG,charu);
voidSortdge(Dgevalue&dgevalue,MGraphG);

//-------------------------------------------------------------------------------
intCreateUDG(MGraph&G,Dgevalue&dgevalue)//構造無向加權圖的鄰接矩陣
{
inti,j,k;
cout<<"請輸入圖中節點個數和邊/弧的條數:";
cin>>G.vexnum>>G.arcnum;
cout<<"請輸入節點:";
for(i=0;i<G.vexnum;++i)
cin>>G.vexs[i];
for(i=0;i<G.vexnum;++i)//初始化數組
{
for(j=0;j<G.vexnum;++j)
{
G.arcs[i][j].adj=MAX;
}
}
cout<<"請輸入一條邊依附的定點及邊的權值:"<<endl;
for(k=0;k<G.arcnum;++k)
{
cin>>dgevalue[k].ch1>>dgevalue[k].ch2>>dgevalue[k].value;
i=LocateVex(G,dgevalue[k].ch1);
j=LocateVex(G,dgevalue[k].ch2);
G.arcs[i][j].adj=dgevalue[k].value;
G.arcs[j][i].adj=G.arcs[i][j].adj;
}
returnOK;
}
intLocateVex(MGraphG,charch)//確定節點ch在圖G.vexs中的位置
{
inta;
for(inti=0;i<G.vexnum;i++)
{
if(G.vexs[i]==ch)
a=i;
}
returna;
}
voidMiniSpanTree_PRIM(MGraphG,charu)//普利姆演算法求最小生成樹
{
inti,j,k;
Closedgeclosedge;
k=LocateVex(G,u);
for(j=0;j<G.vexnum;j++)
{
if(j!=k)
{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
closedge[k].lowcost=0;
for(i=1;i<G.vexnum;i++)
{
k=Minimum(G,closedge);
cout<<"("<<closedge[k].adjvex<<","<<G.vexs[k]<<","<<closedge[k].lowcost<<")"<<endl;
closedge[k].lowcost=0;
for(j=0;j<G.vexnum;++j)
{
if(G.arcs[k][j].adj<closedge[j].lowcost)
{
closedge[j].adjvex=G.vexs[k];
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
}
}
intMinimum(MGraphG,Closedgeclosedge)//求closedge中權值最小的邊,並返回其頂點在vexs中的位置
{
inti,j;
doublek=1000;
for(i=0;i<G.vexnum;i++)
{
if(closedge[i].lowcost!=0&&closedge[i].lowcost<k)
{
k=closedge[i].lowcost;
j=i;
}
}
returnj;
}
voidMiniSpanTree_KRSL(MGraphG,Dgevalue&dgevalue)//克魯斯卡爾演算法求最小生成樹
{
intp1,p2,i,j;
intbj[MAX_VERTEX_NUM];//標記數組
for(i=0;i<G.vexnum;i++)//標記數組初始化
bj[i]=i;
Sortdge(dgevalue,G);//將所有權值按從小到大排序
for(i=0;i<G.arcnum;i++)
{
p1=bj[LocateVex(G,dgevalue[i].ch1)];
p2=bj[LocateVex(G,dgevalue[i].ch2)];
if(p1!=p2)
{
cout<<"("<<dgevalue[i].ch1<<","<<dgevalue[i].ch2<<","<<dgevalue[i].value<<")"<<endl;
for(j=0;j<G.vexnum;j++)
{
if(bj[j]==p2)
bj[j]=p1;
}
}
}
}
voidSortdge(Dgevalue&dgevalue,MGraphG)//對dgevalue中各元素按權值按從小到大排序
{
inti,j;
doubletemp;
charch1,ch2;
for(i=0;i<G.arcnum;i++)
{
for(j=i;j<G.arcnum;j++)
{
if(dgevalue[i].value>dgevalue[j].value)
{
temp=dgevalue[i].value;
dgevalue[i].value=dgevalue[j].value;
dgevalue[j].value=temp;
ch1=dgevalue[i].ch1;
dgevalue[i].ch1=dgevalue[j].ch1;
dgevalue[j].ch1=ch1;
ch2=dgevalue[i].ch2;
dgevalue[i].ch2=dgevalue[j].ch2;
dgevalue[j].ch2=ch2;
}
}
}
}
voidmain()
{
inti,j;
MGraphG;
charu;
Dgevaluedgevalue;
CreateUDG(G,dgevalue);
cout<<"圖的鄰接矩陣為:"<<endl;
for(i=0;i<G.vexnum;i++)
{
for(j=0;j<G.vexnum;j++)
cout<<G.arcs[i][j].adj<<"";
cout<<endl;
}
cout<<"=============普利姆演算法===============\n";
cout<<"請輸入起始點:";
cin>>u;
cout<<"構成最小代價生成樹的邊集為:\n";
MiniSpanTree_PRIM(G,u);
cout<<"============克魯斯科爾演算法=============\n";
cout<<"構成最小代價生成樹的邊集為:\n";
MiniSpanTree_KRSL(G,dgevalue);
}
pascal演算法

program didi;
var
a:array[0..100000] of record
s,t,len:longint;
end;
fa,r:array[0..10000] of longint;
n,i,j,x,y,z:longint;
tot,ans:longint;
count,xx:longint;
procere quick(l,r:longint);
var
i,j,x,y,t:longint;
begin
i:=l;j:=r;
x:=a[(l+r) div 2].len;
repeat
while x>a[i].len do inc(i);
while x<a[j].len do dec(j);
if i<=j then
begin
y:=a[i].len;a[i].len:=a[j].len;a[j].len:=y;
y:=a[i].s;a[i].s:=a[j].s;a[j].s:=y;
y:=a[i].t;a[i].t:=a[j].t;a[j].t:=y;
inc(i);dec(j);
end;
until i>j;
if i<r then quick(i,r);
if l<j then quick(l,j);
end;
function find(x:longint):longint;
begin
if fa[x]<>x then fa[x]:=find(fa[x]);
find:=fa[x];
end;
procere union(x,y:longint);{啟發式合並}
var
t:longint;
begin
x:=find(x);
y:=find(y);
if r[x]>r[y] then
begin
t:=x;x:=y;y:=t;
end;
if r[x]=r[y] then inc(r[x]);
fa[x]:=y;
end;
begin
readln(xx,n);
for i:=1 to xx do fa[i]:=i;
for i:=1 to n do
begin
read(x,y,z);
inc(tot);
a[tot].s:=x;
a[tot].t:=y;
a[tot].len:=z;
end;
quick(1,tot);{將邊排序}
ans:=0;
count:=0;
i:=0;
while count<=x-1 do{count記錄加邊的總數}
begin
inc(i);
with a[i] do
if find(s)<find(t) then
begin
union(s,t);
ans:=ans+len;
inc(count);
end;
end;
write(ans);
end.
Prim
var
m,n:set of 1..100;
s,t,min,x,y,i,j,k,l,sum,p,ii:longint;
a:array[1..100,1..100]of longint;
begin
readln(p);
for ii:=1 to p do
begin
k:=0; sum:=0;
fillchar(a,sizeof(a),255);
readln(x);
m:=[1];
n:=[2..x];
for i:=1 to x do
begin
for j:=1 to x do
begin
read(a[i,j]);
if a[i,j]=0
then a[i,j]:=maxlongint;
end;
readln;
end;
for l:=1 to x-1 do
begin
min:=maxlongint;
for i:=1 to x do
if i in m
then begin
for j:=1 to x do
begin
if (a[i,j]<min)and(j in n)
then begin
min:=a[i,j];
s:=i;
t:=j;
end;
end;
end;
sum:=sum+min;
m:=m+[t];
n:=n-[t];
inc(k);
end;
writeln(sum);
end;
end.

『叄』 用prim演算法求最小生成樹:c語言

把main函數改成:

main(){
GraphMatrix graph = {
"abcd",

{{7,8,Max,15},{12,100,6,20},{Max,100,4,13},{Max,4,8,10}},

};

Edge mst[Max];
int i,j;

prim(graph,mst);
for(j=0;j<Max;j++)
{
printf("%c\t",mst[j].stop_vex);
printf("%c\t",mst[j].start_vex);
printf("%d\n",mst[j].weight);
}
}

還有GraphMatrix結構體里的vexs數組最好定義為vexs[VN+1]給字元串末尾的『\0'留地方。

『肆』 用普里姆演算法求最小生成樹(C++)

求最小生成樹的譜里姆演算法
#include <iostream>
using namespace std;

const int n=6;
const int e=10;
class edgeset
{public :
int front;
int end;
int weight;};

class tree
{public :
int s[n+1][n+1];
edgeset ct[n+1];

void prim(tree &t)
{
int i,j,k,min,t1,m,w;
for(i=1;i<n;i++)
{t.ct[i].front=1;
t.ct[i].end=i+1;
t.ct[i].weight=t.s[1][i+1];}

for(k=2;k<=n;k++)
{min=32767;
m=k-1;

for(j=k-1;j<n;j++)
if(t.ct[j].weight<min)
{min=t.ct[j].weight;
m=j;}
edgeset temp=t.ct[k-1];
t.ct[k-1]=t.ct[m];
t.ct[m]=temp;
j=t.ct[k-1].end;
for(i=k;i<n;i++)
{t1=t.ct[i].end;
w=t.s[j][t1];
if(w<t.ct[i].weight)
{t.ct[i].weight=w;
t.ct[i].front=j;}}}}
};

void main ()
{int j,w;tree t;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i==j)t.s[i][j]=0;
else t.s[i][j]=32767;

for(int k=1;k<=e;k++)
{cout<<"輸入一條邊及邊上的權值 ";
cin>>i>>j>>w;
cout<<endl;
t.s[i][j]=w;
t.s[j][i]=w;}

t.prim(t);
for(i=1;i<n;i++)
{cout<<t.ct[i].front<<" "<<t.ct[i].end<<" "<<t.ct[i].weight<<endl;}
}
我們的實驗上機做了的
運行結果
輸入一條邊及邊上的權值 1 2 6

輸入一條邊及邊上的權值 1 3 1

輸入一條邊及邊上的權值 1 4 6

輸入一條邊及邊上的權值 2 3 5

輸入一條邊及邊上的權值 2 5 3

輸入一條邊及邊上的權值 3 4 7

輸入一條邊及邊上的權值 3 5 5

輸入一條邊及邊上的權值 3 6 4

輸入一條邊及邊上的權值 4 6 2

輸入一條邊及邊上的權值 5 6 6

1 3 1
3 6 4
6 4 2
3 5 5
5 2 3
Press any key to continue
你有的圖不一樣就該頂點和邊就是
const int n=6;
const int e=10;

『伍』 簡述最小生成樹的Prime演算法的思想

因該是prim演算法
假設V是圖中頂點的集合,E是圖中邊的集合,TE為最小生成樹中的邊的集合,則prim演算法通過以下步驟可以得到最小生成樹:
1:初始化:U={u 0},TE={f}.此步驟設立一個只有結點u 0的結點集U和一個空的邊集TE作為最小生成樹的初始形態,在隨後的演算法執行中,這個形態會不斷的發生變化,直到得到最小生成樹為止.
2:在所有u∈U,v∈V-U的邊(u,v)∈E中,找一條權最小的邊(u 0,v 0),將此邊加進集合TE中,並將此邊的非U中頂點加入U中.此步驟的功能是在邊集E中找一條邊,要求這條邊滿足以下條件:首先邊的兩個頂點要分別在頂點集合U和V-U中,其次邊的權要最小.找到這條邊以後,把這條邊放到邊集TE中,並把這條邊上不在U中的那個頂點加入到U中.這一步驟在演算法中應執行多次,每執行一次,集合TE和U都將發生變化,分別增加一條邊和一個頂點,因此,TE和U是兩個動態的集合,這一點在理解演算法時要密切注意.
3:如果U=V,則演算法結束;否則重復步驟2.可以把本步驟看成循環終止條件.我們可以算出當U=V時,步驟2共執行了n-1次(設n為圖中頂點的數目),TE中也增加了n-1條邊,這n-1條邊就是需要求出的最小生成樹的邊.

『陸』 最小生成樹的兩種演算法

主要有兩個:
1.普里姆(Prim)演算法
特點:時間復雜度為O(n2).適合於求邊稠密的最小生成樹。
2.克魯斯卡爾(Kruskal)演算法
特點:時間復雜度為O(eloge)(e為網中邊數),適合於求稀疏的網的最小生成樹。

『柒』 Prim演算法 最小生成樹問題

你的圖里有兩條邊權重一樣,在實際計算前無法事先保證最小生成樹的唯一性,即使是兩個不同的Prim演算法也可能產生不同的結果
當然,計算完之後情況會略有不同,下面會解釋

Prim演算法首先會依次選
E(1,2)=1
E(2,7)=2
E(2,3)=3
然後E(3,4)=E(7,6)=4,會面臨兩種選擇
如果優先選E(3,4)這條邊,那麼下一步仍然會選E(7,6),反過來也一樣,所以這個圖恰好沒影響
繼續下去最終得到
E(1,2)=1
E(2,7)=2
E(2,3)=3
E(3,4)=4
E(7,6)=4
E(4,5)=6
這樣6條邊構成唯一的最小生成樹,總權重是20
(唯一性是因為總權重不超過20的其它子圖確實都不連通)
既然最小生成樹唯一,Kruskal演算法當然也會產生同一棵樹

『捌』 已知圖G如下所示,根據Prim演算法,構造最小生成樹。(要求給出生成過程)

①將帶權連通圖G=的各邊按權從小到大依次排列,如e1,e2,…,em,其中e1的權最小,em的權最大,m為邊數。 ②取權最小的兩條邊構成邊集T0,即T0={e1,e2},從e3起,按次序逐個將各邊加進集合T0中去,若出現迴路則將這條邊排除(不加進去),按此法一直進行到em,最後得到n-1條邊的集合T0={e1,e2,…,en-1},則T0導出的子圖就是圖G的最小生成樹。

『玖』 利用Prim(普里姆)演算法 構造最小生成樹 程序

演算法同樣是解決最小生成樹的問題。

其演算法為:在這n個點中的相通的邊進行排序,然後不斷地將邊添加到集合中(體現了貪心的演算法特點),在並入集合之前,必須檢查一下這兩點是不是在一個集合當中,這就用到了並查集的知識。直到邊的集合達到了n-1個。

與prim演算法的不同:prim演算法為單源不斷尋找連接的最短邊,向外擴展,即單樹形成森林。而Kruskal演算法則是不斷尋找最短邊然後不斷將集合合並,即多樹形成森林。

復雜度的不同:prim演算法的復雜度是O(n^2),其中n為點的個數。Kruskal演算法的復雜度是O(e*loge),其中e為邊的個數。兩者各有優劣,在不同的情況下選擇不同的演算法。

Prim演算法用於求無向圖的最小生成樹

設圖G =(V,E),其生成樹的頂點集合為U。

①、把v0放入U。

②、在所有u∈U,v∈V-U的邊(u,v)∈E中找一條最小權值的邊,加入生成樹。

③、把②找到的邊的v加入U集合。如果U集合已有n個元素,則結束,否則繼續執行②。

其演算法的時間復雜度為O(n^2)

Prim演算法實現:

(1)集合:設置一個數組set(i=0,1,..,n-1),初始值為 0,代表對應頂點不在集合中(注意:頂點號與下標號差1)

(2)圖用鄰接陣表示,路徑不通用無窮大表示,在計算機中可用一個大整數代替。
{先選定一個點,然後從該點出發,與該點相連的點取權值最小者歸入集合,然後再比較在集合中的兩點與其它各點的邊的權值最小者,再次進入集合,一直到將所有的點都歸入集合為止。}

『拾』 怎樣用prim演算法求全部最小生成樹

//prim演算法
#include<iostream>
using namespace std;

#define MAXVEX 10
#define MAX 65000
typedef char VexType;
typedef float AdjType;
struct GraphMatrix
{
VexType vexs[MAXVEX]; //頂點信息
AdjType arcs[MAXVEX][MAXVEX]; //邊信息
int n; //圖的頂點個數
};

struct Edge
{
int start_vex; //邊的起點
int stop_vex; //邊的終點
AdjType weight; //邊的權
};

void edgeCopy(Edge *to,Edge *from)
{
to->start_vex=from->start_vex;
to->stop_vex=from->stop_vex;
to->weight=from->weight;
}

void prim(GraphMatrix *pgraph,Edge *mst)
{
int i,j;
int vx,vy;
int min;
AdjType weight,minweight;
Edge edge;

for(i=0;i<pgraph->n-1;++i)
{
mst[i].start_vex=0;
mst[i].stop_vex=i+1;
mst[i].weight=pgraph->arcs[0][i+1];
}
for(i=0;i<pgraph->n-1;++i)
{
minweight=MAX;
min=i;
for(j=i;j<pgraph->n-1;++j)
if(mst[j].weight<minweight)
{
minweight=mst[j].weight;
min=j;
}
edgeCopy(&edge,&mst[min]);
edgeCopy(&mst[min],&mst[i]);
edgeCopy(&mst[i],&edge);
vx=mst[i].stop_vex;
for(j=i+1;j<pgraph->n-1;++j)
{
vy=mst[j].stop_vex;
weight=pgraph->arcs[vx][vy];
if(weight<mst[j].weight)
{
mst[j].weight=weight;
mst[j].start_vex=vx;
}
}
}
}

熱點內容
linux線程串口 發布:2025-05-11 13:03:00 瀏覽:76
nds伺服器ip地址 發布:2025-05-11 12:43:32 瀏覽:869
舒聽瀾卓禹安書名叫什麼 發布:2025-05-11 12:36:44 瀏覽:268
java開發web應用 發布:2025-05-11 12:35:51 瀏覽:696
鯊魚影視怎麼緩存電視 發布:2025-05-11 12:35:48 瀏覽:549
ios小項目源碼 發布:2025-05-11 12:35:47 瀏覽:756
為什麼打開的三菱程序不能編譯 發布:2025-05-11 12:16:40 瀏覽:21
ftp定價是怎麼回事 發布:2025-05-11 12:09:18 瀏覽:334
android敏捷開發 發布:2025-05-11 11:56:49 瀏覽:80
腳本pon 發布:2025-05-11 11:52:27 瀏覽:826