805
汽車大全
【算法小總結】Prim算法與Kruskal算法探索
以前以為自己用的生成最小生成樹的方法是Prim算法,今天自己拜讀了《數據結構與算法分析》之後才知道自己有多愚蠢,原來以前一直用的是KrusKal算法。。。。。。
今天好好說道說道這兩個算法:
KrusKal算法用於稀疏圖,貪心策略,連續的按照最小的權值選擇邊。
Prim算法用於稠密圖,也是貪心策略,每次取離小生成樹最近的點作為生成樹的心點,並入生成樹內生成新的小生成樹,知道所有節點均被納入生成樹後結束。
這兩種方法均可得到點點之間路徑最短的聯通圖。
例如這個例子:
用Prim算法的過程:
用KrusKal算法的過程:
下麵我編碼來實現Prim算法:
(測試數據均是圖一)
#include<stdio.h> #include<string.h> #define INF 0x11111110 int map[2010][2010],Tree[2010]; int closeset[2010];//節點依附的點(就是與生成樹裏那個點鏈接) int lowcost[2010];//節點到生成樹的最短距離 int sum=0; void Prim(int n) { int i,j,k; int min; Tree[1]=1;//先把 1放在生成樹裏 for(i=1;i<=n;i++) { lowcost[i]=map[i][1];//所有節點與生成樹的最短距離初始化 closeset[i]=1;//i依附於誰 (初始化都依附於1) } for(j=1;j<=n-1;j++)//n個節點有n-1條邊 { min=INF; //找到離生成樹最近的點 for(i=1;i<=n;i++) { if(!Tree[i]&&lowcost[i]<min) { min=lowcost[i]; k=i; } } printf("鏈接%d %d 距離為%d\n",k,closeset[k],min); sum+=min; Tree[k]=1; //把 k並入生成樹 //找到離新加入的點最近的點,更新那個點距生成樹的距離 for(i=1;i<=n;i++) { if(!Tree[i]&&map[k][i]<lowcost[i]) { lowcost[i]=map[k][i];//更新最小值 closeset[i]=k;//記錄新的依附點 } } } } int main() { int i,j,n,m,x,y,z; while(scanf("%d %d",&n,&m)!=EOF) { memset(Tree,0,sizeof(Tree));//用來記錄節點是否在生成樹中 memset(map,INF,sizeof(map)); for(i=0;i<m;i++) { scanf("%d %d %d",&x,&y,&z); map[x][y]=z; map[y][x]=z; } printf("生成樹的合成順序:\n"); Prim(n); printf("生成樹的最短距離:%d\n",sum); } return 0; }
輸入:
7 12
1 4 1
1 2 2
1 3 4
2 4 3
2 5 10
3 4 2
3 5 6
6 4 8
6 7 1
5 4 7
5 7 6
7 4 4
輸出:
生成樹的合成順序:
鏈接4 1 距離為1
鏈接2 1 距離為2
鏈接3 4 距離為2
鏈接7 4 距離為4
鏈接6 7 距離為1
鏈接5 3 距離為6
生成樹的最短距離:16
下麵我編碼來實現KrusKal算法:
#include<iostream> #include<algorithm> using namespace std; struct node { int a,b; int len; }per[5000]; int cmp(node x,node y) { if(x.len!=y.len) return x.len<y.len; } int main() { int i,sum,n,m,num; int flag[200]; while(scanf("%d %d",&n,&m),n!=0) { for(i=0;i<m;i++) { scanf("%d%d%d",&per[i].a,&per[i].b,&per[i].len); } sort(per,per+m,cmp); for(i=1;i<=n;i++) flag[i]=1; flag[per[0].a]=0; sum=0; for(i=0;i<m;i++) { num=flag[per[i].a]+flag[per[i].b]; if(num==1) { printf("鏈接%d %d 長度%d\n",per[i].a,per[i].b,per[i].len); sum+=per[i].len; flag[per[i].a]=flag[per[i].b]=0; i=0; } } printf("生成樹路徑總和%d\n",sum); } return 0; }
輸入
7 12
1 4 1
1 2 2
1 3 4
2 4 3
2 5 10
3 4 2
3 5 6
6 4 8
6 7 1
5 4 7
5 7 6
7 4 4
輸出:
鏈接6 7 長度1
鏈接7 4 長度4
鏈接1 4 長度1
鏈接3 4 長度2
鏈接1 2 長度2
鏈接5 7 長度6
生成樹路徑總和16
區別一目了然........
最後更新:2017-04-03 05:39:37