導航:首頁 > 源碼編譯 > prim演算法最初的點隨意取嗎

prim演算法最初的點隨意取嗎

發布時間:2022-08-18 07:11:41

『壹』 prim演算法不是很理解啊

其實它就是一個貪心

不知道你學過dijkstra沒有,這兩個是很類似的(代碼上也是,樸素實現好象就差1句)。
如果點A是未加入樹中最近的那個點,那麼我們貪心地加入A肯定是最優的!
假設B是任意一個未加入樹中不是最近的點,而我們這次加入了B。
那麼接下來可能有兩種情況再加入A:
1、直接加入A,這跟我們直接加入A是一樣的,但我們不能保證當時加入B是最優的。
2、用B更新邊後加入A,但是A比B要離樹近,所以之前加入A,再用A更新B然後加入B要比這種情況更優。
綜上,我們每次加入A總是最優的!

所以prim是對的。

『貳』 Prim演算法,求大牛通俗易懂地解釋下為什麼成立。。。

prim演算法就是把點分成兩個集合,一個集合裡麵包含已經加入生成樹的點,另一個包含未加入的,然後不斷在兩個集合之間找最短的邊,直到所有的點都加入到生成樹中,這時候就構成了最小生成樹。

『叄』 KRUSKAL演算法和PRIM演算法

不是吧,網路白科裡面有這倆個演算法的詳細的講解,你可以去查查

『肆』 利用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演算法

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演算法,解釋一步就好!

到C時可以得到的結果是:到2的最短長度為5,到5的最短長度為6,所以選最小的那個長度為5,即選擇下一個連接節點為2,即得到了D圖

『捌』 根據PRIM演算法構造最小生成樹怎麼確定出發點

用pascal語言的,可以轉成C++很容易的
首先定義數據類型:
type adjmatrix=array [1..n,1..n] of real;
//定義一個n*n的矩陣類型adjmatrix,以便存儲鄰接矩陣//
edge=record
beg,en:1..n;
length:real;
end;
//定義邊的存儲結構為edge,其中beg是邊的起點, en 是邊的終點,length是邊的權值//
treetype=array [1..n-1] of edge;
//定義一個基類型為edge的數組類型 treetype,其元素個數為n-1個//
var net:adjmatrix;
//定義一個adjmatrix類型的變數net,圖的鄰接矩陣就存放在net中//
tree:treetype;
//定義一個treetype類型的變數tree,tree中可以存放n-1條邊的信息,包括起點、終點及權值。在演算法結束後,最小生成樹的n-1 條邊就存放在tree中//
演算法如下(設n為構造的出發點):
procere prim(net:adjmatrix;var tree:treetype);
//過程首部.參數的含義是:值參數net傳遞圖的鄰接矩陣,變參tree指明最小生成樹的存放地址//
begin
for v:=1 to n-1 do
//此循環將頂點n與圖中其它n-1個頂點形成的n-1條邊存放在變數tree中//
[tree[v].beg:=n;
tree[v].en:=v;
tree[v].length:=net[v]]
for k:=1 to n-1 do
//此循環執行演算法思想中的步驟2,循環體每執行一次,TE中將增加一條邊,在演算法中,這條增加的邊存放在變數tree中的第k個元素上,可以這樣認為,tree中從第1到第k號元素中存放了TE和U的信息。注意:在演算法思想中我們特別提醒了TE和U的動態性,表現在演算法中,這種動態性 體現在循環變數k的變化上。//
[min:=tree[k].length;
for j:=k to n-1 do
if tree[j].length<min then
[min:=tree[j].length;
m:=j;]
//上面兩條語句用於搜索權值最小的邊//
v:=tree[m].en;
//此語句記錄剛加入TE中的邊的終點,也即即將加入U中的頂點//
edge:=tree[m];
tree[m]:=tree[k];
tree[k]:=edge;
//上面三句用於將剛找到的邊存儲到變數tree的第k號元素上//
for j:=k+1 to n-1 do
//此循環用於更新tree中第k+1到第n-1號元素。更新以後這些元素中的en子項是各不相同的,它們的全部就是集合V-U;beg子項則可以相同,但它們需滿足兩個條件:一是應屬於集合U;另一是beg子項和en子項行成的邊,在所有與頂點en聯系的邊中權值應最小。//
[d:=net[v.tree[j].en];
if d<tree[j].length
then [tree[j].length:=d;
tree[j].beg:=v;]
]
]
for j:=1 to n-1 do
//此循環用於輸出最小生成樹//
writeln(tree[j].beg,tree[j].en,tree[j].length);
end;

『玖』 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。

『拾』 數據結構(prim演算法)

開始時將v1加入U後,更新ee中的值應該是0 6 1 2 無窮 無窮;
將v3加入U後,更新ee中的值應該是0 5 0 2 6 4;
怎麼會出現你說的0 6 0 5 無窮無窮的情況呢?
for(j = 0;j < G.vexnum;j++)中不是有條件判斷么,要在k到j的距離小於ee[j]的value值時才會更新ee[j]啊。

閱讀全文

與prim演算法最初的點隨意取嗎相關的資料

熱點內容
壓縮包製作後照片順序怎麼改 瀏覽:680
fibonacci數列演算法 瀏覽:775
產品經理要和程序員吵架嗎 瀏覽:252
grub2命令行 瀏覽:618
無法獲取加密卡信息 瀏覽:774
雲伺服器網卡充值 瀏覽:509
編程就是軟體 瀏覽:49
伺服器如何添加許可權 瀏覽:437
引用指針編程 瀏覽:851
手機加密日記本蘋果版下載 瀏覽:63
命令行括弧 瀏覽:176
java程序升級 瀏覽:490
排序演算法之插入類 瀏覽:227
gcccreate命令 瀏覽:73
海爾監控用什麼app 瀏覽:64
系統盤被壓縮開不了機 瀏覽:984
linuxredis30 瀏覽:541
狸窩pdf轉換器 瀏覽:697
ajax調用java後台 瀏覽:906
活塞式壓縮機常見故障 瀏覽:615