最小生成树实验
一、實驗目的
1.進一步掌握圖的結構及非線性特點,遞歸特點和動態性。
2.進一步鞏固最小生成樹的兩種求解算法。
二、實驗原理
從任意一頂點 v0 開始選擇其最近頂點 v1 構成樹 T1,再連接與 T1 最近頂點 v2 構成樹 T2, 如此重復直到所有頂點均在所構成樹中為止。
最小生成樹(MST):權值最小的生成樹。
生成樹和最小生成樹的應用:要連通n個城市需要n-1條邊線路。可以把邊上的權值解釋為線路的造價。則最小生成樹表示使其造價最小的生成樹。
構造網的最小生成樹必須解決下面兩個問題:
1、盡可能選取權值小的邊,但不能構成回路;
2、選取n-1條恰當的邊以連通n個頂點;
MST性質:假設G=(V,E)是一個連通網,U是頂點V的一個非空子集。若(u,v)是一條具有最小權值的邊,其中u∈U,v∈V-U,則必存在一棵包含邊(u,v)的最小生成樹。
prim算法假設G=(V,E)是連通的,TE是G上最小生成樹中邊的集合。算法從U={u0}(u0∈V)、TE={}開始。重復執行下列操作:
在所有u∈U,v∈V-U的邊(u,v)∈E中找一條權值最小的邊(u0,v0)并入集合TE中,同時v0并入U,直到V=U為止。
此時,TE中必有n-1條邊,T=(V,TE)為G的最小生成樹。
?Prim算法的核心:始終保持TE中的邊集構成一棵生成樹。
注意:prim算法適合稠密圖,其時間復雜度為O(n^2),其時間復雜度與邊得數目無關,而kruskal算法的時間復雜度為O(eloge)跟邊的數目有關,適合稀疏圖
三、參考程序
#include<stdio.h>
#define max 7
int quan[max][max];//放權值
int useing[max],used[max];//useing表示已經被選中的節點,used表示未被選中的節點
struct biao{
int index;
int quanzhi;
}b[max-1];//用來存放quanzhi數組中某一行的數據,
void tree(){
int min=1000,j,miny,minx=1,i=0,k,uing=1,ud=1,count=0,z,t=0,w=0;
//min=1000表示路不通。 minx表示第幾行,miny 表示第幾列,count用來計算總的最小權值
while(true){
i=minx;
useing[uing]=i;//把被選中的節點給useing我們從1節點開始
uing++;
for(k=1;k<max;k++){
if(minx==used[k]){
used[k]=1000;//如果節點亦被選中把該位置=1000
}
}
printf("\n i--%d\n",i);
for(k=1, j=1;j<max;j++,k++){//給b數組初始化
b[k].index=j;//下表給它
b[k].quanzhi=quan[i][j];//權值給他
}//for
min=1000;
for(k=1;k<max;k++){//尋找與該節點相連的權值最小的那個節點
if(min>b[k].quanzhi){
min=b[k].quanzhi;
miny=k;//記錄下該節點的下表
}
}
quan[i][miny]=1000;
quan[miny][i]=1000; //把找到的節點的數=1000;
printf("\n---1---\n");
/*
printf("\n min--%d\n",min);
printf("\n minx--%d\n",minx);
for(i=1;i<max;i++){
printf("%d\t",b[i].quanzhi);
}
printf("\n");
for(i=1;i<max;i++){
for(j=1;j<max;j++)
printf("%d\t",quan[i][j]);
printf("\n");
}
*/
minx=miny;//把找到的節點的下表給minx,為了便利找到該節點的最小權值
z=0;
for(i=1;i<max;i++){
if(miny==useing[i]){//形成環路了
z=1;
w=1;
}
}
if(z==1){
for(i=1;i<max;i++){//從還未 被趙國的節點再次開始開始
if(used[i]!=1000){
minx=used[i];//把未被選中過的下標給minx
used[i]=1000;//并把used該位置=1000
break;
}
}
}
// useing[uing]=minx;
// printf("\n using--%d\n",uing);
// uing++;
count=count+min;//求最小權值總和
// printf("\n--count-%d---\n",count);
if(t==6)//結束循環,
break;
t=0;
for(i=1;i<max;i++){//判斷所有頂點是否全被便利過
if(used[i]==1000){
t++;
}
}
if(w==1){//減去那個形成環路時多加的權值
count=count-min;
}
w=0;
}
for(i=1;i<max;i++){
printf("%d\t",useing[i]);
}
printf("\n");
for(i=1;i<max;i++){
printf("%d\t",used[i]);
}
printf("\n");
printf("\n--count1-%d---\n",count);
}
int main(){
int i,j,t=0,number,weight;;
for(i=0;i<max;i++){
for(j=0;j<max;j++)
quan[i][j]=1000;
}
for(i=0;i<max;i++){
used[i]=i;
useing[i]=0;
}
FILE *fr;
fr = fopen("D:\\123.txt","r");
if(!fr)
{
printf("fopen failed\n");
}
while(fscanf(fr,"%d%d%d", &i, &j, &weight) != EOF)
{
quan[i][j] = weight;
quan[j][i] = weight;
}
for(i=1;i<max;i++){
for(j=1;j<max;j++)
printf("%d\t",quan[i][j]);
printf("\n");
}
for(i=1;i<max;i++){
printf("%d\t",useing[i]);
}
for(i=1;i<max;i++){
printf("%d\t",used[i]);
}
tree();
return 0;
}
轉載于:https://www.cnblogs.com/huifeidezhuzai/p/9278962.html
總結
- 上一篇: 【Spring】—— 自动装配
- 下一篇: 一场面试,用20秒介绍自己顺便教训了领导