『壹』 普里姆演算法是什麼
在計算機科學中,普里姆(也稱為Jarník's)演算法是一種貪婪演算法,它為加權的無向圖找到一個最小生成樹 。
相關簡介:
這意味著它找到邊的一個子集,能夠形成了一個包括所有頂點的樹,其中在樹中所有邊的權重總和最小。該演算法通過從任意起始頂點開始一次給樹增加一個頂點來操作,在每個步驟中添加從樹到另一個頂點的花費最小的可能的連接。
該演算法由捷克數學家沃伊茨奇·賈尼克於1930年開發後,後來在1957年被計算機科學家羅伯特·普里姆,以及在1959年被艾茲赫爾·戴克斯特拉重新發現和重新出版。因此,它有時也被稱為Jarník演算法,普里姆-jarník演算法。普里姆-迪克斯特拉演算法或者DJP演算法。
這個問題的其他眾所周知的演算法包括克魯斯卡爾演算法和 Borvka's演算法。這些演算法在一個可能的非連通圖中找到最小生成森林;相比之下,普里姆演算法最基本的形式只能在連通圖中找到最小生成樹。然而,為圖中的每個連通分量單獨運行普里姆演算法,也可以用於找到最小生成森林。
就漸近時間復雜度而言,這三種演算法對於稀疏圖來說速度相同,但比其他更復雜的演算法慢。然而,對於足夠密集的圖,普里姆演算法可以在線性時間內運行,滿足或改進其他演算法的時間限制。
『貳』 普里姆演算法
可以這么理解:因為最小生成樹是包含所有頂點的所以開始lowcost先儲存到第一個點的所有值,然後執行下面演算法,找到最小值並記錄是第幾個點,比如說這個點是3,這樣有了一條1-3得道路已經確定,現在從3出發找從3出發到其他頂點的路徑,如果這個從3出發到達的路徑長度比從1出發的短,則更新lowcost,這樣使得lowcost保存一直到達該頂點的最短路徑。比如1-4是5,3-4是4,則lowcost從原來的5被改為4。
『叄』 普里姆演算法的相關信息
1)演算法的基本思想:
普里姆演算法的基本思想:普里姆演算法是另一種構造最小生成樹的演算法,它是按逐個將頂點連通的方式來構造最小生成樹的。
從連通網路N = { V, E }中的某一頂點u0出發,選擇與它關聯的具有最小權值的邊(u0, v),將其頂點加入到生成樹的頂點集合U中。以後每一步從一個頂點在U中,而另一個頂點不在U中的各條邊中選擇權值最小的邊(u, v),把該邊加入到生成樹的邊集TE中,把它的頂點加入到集合U中。如此重復執行,直到網路中的所有頂點都加入到生成樹頂點集合U中為止。
假設G=(V,E)是一個具有n個頂點的帶權無向連通圖,T(U,TE)是G的最小生成樹,其中U是T的頂點集,TE是T的邊集,則構造G的最小生成樹T的步驟如下:
(1)初始狀態,TE為空,U={v0},v0∈V;
(2)在所有u∈U,v∈V-U的邊(u,v)∈E中找一條代價最小的邊(u′,v′)並入TE,同時將v′並入U;
重復執行步驟(2)n-1次,直到U=V為止。
在普里姆演算法中,為了便於在集合U和(V-U)之間選取權值最小的邊,需要設置兩個輔助數組closest和lowcost,分別用於存放頂點的序號和邊的權值。對於每一個頂點v∈V-U,closest[v]為U中距離v最近的一個鄰接點,即邊(v,closest[v])是在所有與頂點v相鄰、且其另一頂點j∈U的邊中具有最小權值的邊,其最小權值為lowcost[v],即lowcost[v]=cost[v][closest[v]],採用鄰接表作為存儲結構:
設置一個輔助數組closedge[]:
lowcost域存放生成樹頂點集合內頂點到生成樹外各頂點的各邊上的當前最小權值;
adjvex域記錄生成樹頂點集合外各頂點距離集合內哪個頂點最近(即權值最小)。
應用Prim演算法構造最小生成樹的過程:
『肆』 最小生成樹 普里姆演算法有問
普里姆演算法構造最小生成樹演算法的思想是:選擇一個結點,然後從這個結點開始,選擇權值最小的邊,用一條邊連接,然後再以前面的那個結點開始,和你連接的那個結點作為根節點,再選擇權值最小的邊進行連接。
對權值給出解釋:以上圖為例,權值就是你第一個圖那幾條邊(弧)上,所標的數字。
對樓主所提出的問題:並不是連接那圓圈中最小的圓圈,如果沒錯的話,那圓圈中的數字表示的是V1---V6六個頂點,並不是代表數字,以3和6為頂點,找權值最小邊,顯然6——4為最小,即權值為2,頂點364相連接的時候各以364為頂點尋找最小邊,應該先從6連接到2,那麼現在加入頂點的為3642頂點,現在以3642為頂點尋找最小邊,應該從2連接到1,現在被連接的有63421,在以63421為頂點尋找最小邊
出現了問題:如果以5為權值的話,無論從2連接到4還是從3連接到4都出現了環,當然我們知道數中是不能出現環的,所以尋找次小的,剩餘5與13之間權值最小為13.所以將1連接5,即得到最小生成樹。
樓主可以按照我說的在紙上畫一下試試
從6連接到3因為有前提條件:從頂點V3開始用普里姆方法求其最小生成數,可見是從頂點3連接到6,而不是從6連接到3
希望可以解決樓主的疑惑,謝謝!
『伍』 什麼是Prim演算法
Prim演算法
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](i=0,1,..,n-1),初始值為 0,代表對應頂點不在集合中(注意:頂點號與下標號差1)
(2)圖用鄰接陣表示,路徑不通用無窮大表示,在計算機中可用一個大整數代替。
參考程序
/* Prim.c
Copyright (c) 2002, 2006 by ctu_85
All Rights Reserved.
*/
/* The impact of the situation of articulation point exists can be omitted in Prim algorithm but not in Kruskal algorithm */
#include "stdio.h"
#define maxver 10
#define maxright 100
int main()
{
int G[maxver][maxver],in[maxver]=,path[maxver][2];
int i,j,k,min=maxright;
int v1,v2,num,temp,status=0,start=0;
restart:
printf("Please enter the number of vertex(s) in the graph:\n");
scanf("%d",&num);
if(num>maxver||num<0)
{
printf("Error!Please reinput!\n");
goto restart;
}
for(j=0;j<num;j++)
for(k=0;k<num;k++)
{
if(j==k)
G[j][k]=maxright;
else
if(j<k)
{
re:
printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);
scanf("%d",&temp);
if(temp>=maxright||temp<-1)
{
printf("Invalid input!\n");
goto re;
}
if(temp==-1)
temp=maxright;
G[j][k]=G[k][j]=temp;
}
}
for(j=0;j<num;j++)
{
status=0;
for(k=0;k<num;k++)
if(G[j][k]<maxright)
{
status=1;
break;
}
if(status==0)
break;
}
do
{
printf("Please enter the vertex where Prim algorithm starts:");
scanf("%d",&start);
}while(start<0||start>num);
in[start-1]=1;
for(i=0;i<num-1&&status;i++)
{
for(j=0;j<num;j++)
for(k=0;k<num;k++)
if(G[j][k]<min&&in[j]&&(!in[k]))
{
v1=j;
v2=k;
min=G[j][k];
}
if(!in[v2])
{
path[i][0]=v1;
path[i][1]=v2;
in[v1]=1;
in[v2]=1;
min=maxright;
}
}
if(!status)
printf("We cannot deal with it because the graph is not connected!\n");
else
{
for(i=0;i<num-1;i++)
printf("Path %d:vertex %d to vertex %d\n",i+1,path[i][0]+1,path[i][1]+1);
}
return 1;
}
Prim演算法。
設圖G =(V,E),其生成樹的頂點集合為U。
①、把v0放入U。
②、在所有u∈U,v∈V-U的邊(u,v)∈E中找一條最小權值的邊,加入生成樹。
③、把②找到的邊的v加入U集合。如果U集合已有n個元素,則結束,否則繼續執行②。
其演算法的時間復雜度為O(n^2)
參考程序
//Prim 演算法 讀入頂點數(n)、邊數(m),邊的起始點和權值 用鄰接矩陣儲存
//例如
//7 12 (7個頂點12條邊)
//1 2 2
//1 4 1
//1 3 4
//2 4 3
//2 5 10
//3 4 2
//4 5 7
//3 6 5
//4 6 8
//4 7 4
//5 7 6
//6 7 1
#include <stdio.h>
#include <string.h>
int main()
{
int m , n;
int a[201][201] , mark[201] , pre[201] , dist[201];
int s , t , w;
int i , j , k , min , tot;
freopen("Prim.txt" , "r" , stdin);
//讀入數據
memset(a , 0 , sizeof(a));
scanf("%d %d" , &n , &m);
for (i = 0; i < m; i ++)
{
scanf("%d %d %d" , &s , &t , &w);
a[s][t] = w; a[t][s] = w;
}
//賦初值
memset(mark , 0 , sizeof(mark));
memset(pre , 0 , sizeof(pre));
memset(dist , 9999 , sizeof(dist));
dist[1] = 0;
//Prim
for (i = 1; i <= n; i ++)
{
min = 9999; k = 0;
for (j = 1; j <= n; j ++)
if ((mark[j] == 0) && (dist[j] < min)) {min = dist[j]; k = j;}
if (k == 0) break;
mark[k] = 1;
for (j = 1; j <= n; j ++)
if ((mark[j] == 0) && (a[k][j] < dist[j]) && (a[k][j] > 0))
{
dist[j] = a[k][j];
pre[j] = k;
}
}
tot = 0;
for (i = 1; i <= n; i ++) tot += dist[i];
printf("%d\n" , tot);
return 0;
}
『陸』 prim演算法是什麼
普里姆演算法(Prim演算法),圖論中的一種演算法,可在加權連通圖里搜索最小生成樹。意即由此演算法搜索到的邊子集所構成的樹中,不但包括了連通圖里的所有頂點(英語:Vertex (graph theory)),且其所有邊的權值之和亦為最小。
演算法的發展:
該演算法於1930年由捷克數學家沃伊捷赫·亞爾尼克(英語:Vojtěch Jarník)發現;並在1957年由美國計算機科學家羅伯特·普里姆(英語:Robert C. Prim)獨立發現;1959年,艾茲格·迪科斯徹再次發現了該演算法。因此,在某些場合,普里姆演算法又被稱為DJP演算法、亞爾尼克演算法或普里姆-亞爾尼克演算法。
『柒』 什麼事普里姆演算法
是圖的最小生成樹的一種構造演算法。 假設 WN=(V,{E}) 是一個含有 n 個頂點的連通網,TV 是 WN 上最小生成樹中頂點的集合,TE 是最小生成樹中邊的集合。顯然,在演算法執行結束時,TV=V,而 TE 是 E 的一個子集。在演算法開始執行時,TE 為空集,TV 中只有一個頂點,因此,按普里姆演算法構造最小生成樹的過程為:在所有「其一個頂點已經落在生成樹上,而另一個頂點尚未落在生成樹上」的邊中取一條權值為最小的邊,逐條加在生成樹上,直至生成樹中含有 n-1條邊為止。 補充:closedge的類型: struct { VertexData Adjvex; int Lowcost; }closedge[MAX_VERTEX_NUM]; //求最小生成樹的輔助數組 void MiniSpanTree_P( MGraph G, VertexType u ) { //用普里姆演算法從頂點u出發構造網G的最小生成樹 k = LocateVex ( G, u ); closedge[k].Lowcost = 0; // 初始,U={u} for ( j=0; j<G.vexnum; ++j ) // 輔助數組初始化 if (j!=k) closedge[j] = { u, G.arcs[k][j] }; for ( i=0; i<G.vexnum; ++i ) { 繼續向生成樹上添加頂點; } k = minimum(closedge); // 求出加入生成樹的下一個頂點(k) printf(closedge[k].Adjvex, G.vexs[k]); // 輸出生成樹上一條邊 closedge[k].Lowcost = 0; // 第k頂點並入U集 for (j=0; j<G.vexnum; ++j) //修改其它頂點的最小邊 if ( G.arcs[k][j] < closedge[j].Lowcost ) closedge[j] = { G.vexs[k], G.arcs[k][j] }; }
『捌』 什麼是普里姆演算法
構造最小生成樹用的,使用貪心策 略。prime演算法的基本思想 1.清空生成樹,任取一個頂點加入 生成樹 2.在那些一個端點在生成樹里,另 一個端點不在生成樹里的邊中,選 取一條權最小的邊,將它和另一個 端點加進生成樹 3.重復步驟2,直到所有的頂點都 進入了生成樹為止,此時的生成樹 就是最小生成樹
『玖』 普里姆演算法的普里姆演算法的實現
為了便於在兩個頂點集U和V-U之間選擇權最小的邊,建立了兩個輔助數組closest和lowcost,它們記錄從U到V-U具有最小權值的邊,對於某個j∈V-U,closest[j]存儲該邊依附的在U中的頂點編號,lowcost[j]存儲該邊的權值。
為了方便,假設圖G採用鄰接矩陣g存儲,對應的Prim(g,v)演算法如下:
void Prim(MatGraph g,int v) //輸出求得的最小生樹的所有邊
{ int lowcost[MAXVEX]; //建立數組lowcost
int closest[MAXVEX]; //建立數組closest
int min,i,j,k;
for (i=0;i<g.n;i++) //給lowcost[]和closest[]置初值
{ lowcost[i]=g.edges[v][i];
closest[i]=v;
}
for (i=1;i<g.n;i++) //構造n-1條邊
{ min=INF; k=-1;
for (j=0;j<g.n;j++) //在(V-U)中找出離U最近的頂點k
if (lowcost[j]!=0 && lowcost[j]<min)
{ min=lowcost[j];
k=j; //k為最近頂點的編號
}
printf( 邊(%d,%d),權值為%d
,closest[k],k,min);
lowcost[k]=0; //標記k已經加入U
for (j=0;j<g.n;j++) //修正數組lowcost和closest
if (g.edges[k][j]!=0 && g.edges[k][j]<lowcost[j])
{ lowcost[j]=g.edges[k][j];
closest[j]=k;
}
}
}
普里姆演算法中有兩重for循環,所以時間復雜度為O(n2),其中n為圖的頂點個數。由於與e無關,所以普里姆演算法特別適合於稠密圖求最小生成樹。
『拾』 Prim演算法的實現過程
G=(V,E)
①初始化:讀入的數據用鄰接矩陣x存儲,一個一維布爾型數組chosen,記錄第i個節點是否已選,初始值除1外全部設為false,記錄權值的變數cost賦值為0;
以下②到④循環執行v-1次(每次生成一條邊,運行(點的個數減1)次後,生成一棵最小生成樹):
②臨時變數p賦值為無限大,用於記錄當前最小值;
③二重循環(外循環i,內循環j)掃描鄰接矩陣:如果chosen[i]=true(也就是說第i個點已選),那麼掃描x[i],如果not(chosen[j])(也就是說第j個點未選),那麼如果x[i,j]<p,那麼p賦值為x[i,j],臨時變數q賦值為j;
④把cost賦值為cost+o,把chosen[q]賦值為true(也就是說第j個點已選);
⑤輸出cost。
一、以上給出具體的運行過程。這個演算法的策略就是貪心,和dijkstra差不多,每次都選擇未選的邊中權值最小的那一條,直到生成最小生成樹。用chosen的目的就是保證生成過程中沒有環出現,也就是說保證選擇的邊不會通向一個已經包含在生成樹中的點。
二、這個只輸出最小生成樹的每條邊權值之和,如果要輸出整棵最小生成樹,加一個[1..n,1..2]的數組,在第④步的時候把每次選的邊記錄下來就可以了。
三、用小頂堆在第③步優化一下的話就不用每次都掃描那麼多邊了,只不過建堆維護堆代碼寫起來很麻煩。
四、prim適合用於比較稠密的網,點數和邊數差不多的時候效率很惡心,一般都用kruskal。