日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

克鲁斯卡尔算法建立最小生成树

發布時間:2024/1/1 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 克鲁斯卡尔算法建立最小生成树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

克魯斯卡爾算法,是每次選出權值最小的邊構成最小生成樹,選出邊時,要避免形成環。最終選出結點數減一條邊即可。(避免形成環的問題,采用標號法(并查集),一開始,每個結各自為一個集合,分別給出各自不同大小的標號,選出的邊的兩端結點的標號將大的那個改成小的,以后選出的邊的端點標號不能相同。)

#include<iostream> #define N 100 int sum=0;//權值和 using namespace std; //邊節點 typedef struct vexnode {int adjvex;char v;struct vexnode *nextarc;float info; }ArNode; typedef struct Vnode{ //頂點信息 char data;ArNode *firstarc; //指向第一個邊結點 }Vonde,Adjust[100]; typedef struct {Adjust survice;//鄰接表 int vexnum,acrnum;//圖的當前頂點數和邊數 }ALgraph;//鄰接表查找int locate1(ALgraph&R, char v,int n){//找出字符為v的下標 int j,i;for(i=1;i<=n;i++){if(R.survice[i].data==v){j=i;}}return j;} void creatUND(ALgraph &R){char v1,v2;//頂點的數據值 int i1,i2;//輸入的兩個頂點的位置和權值 float i3;//權值 printf("請輸入頂點數和邊數:"); cin>>R.vexnum>>R.acrnum; //輸入頂點數和邊數 printf("請輸入各個頂點的值:\n"); for(int i=1;i<=R.vexnum;i++){cin>>R.survice[i].data;//輸入各個頂點的信息 R.survice[i].firstarc=NULL;}printf("請輸入每條邊依附的兩個結點和權值:\n");for(int i=1;i<=R.acrnum;i++){cin>>v1>>v2>>i3;i1=locate1(R,v1,R.vexnum);i2=locate1(R,v2,R.vexnum);ArNode *p=new ArNode;p->info=i3; //記錄權值 p->v=v1;//記錄邊點的值 p->adjvex=i2;// 記錄頂點的值 p->nextarc=R.survice[i2].firstarc; //利用頭插法把第i1個的頂點插入到第i2個鄰接表中 R.survice[i2].firstarc=p;//建立的鄰接表表示的圖為有向圖,所以只記錄一邊,所以下面的部分代碼給注釋掉了 /* ArNode *p1=new ArNode;p1->adjvex=i1;//記錄頂點的位置 p1->info=i3;//記錄權值 p1->v=v2;//記錄邊點的值 p1->nextarc=R.survice[i1].firstarc;R.survice[i1].firstarc=p1;// 將新節點*p2插入頂點Vi1的鄰接表中 */} /* ArNode *p2; //這部分是將鄰接表表示的圖輸出 for(int i=1;i<=R.vexnum;i++){p2=R.survice[i].firstarc;while(p2){printf("<%c , %c> : %.1f ",R.survice[i].data,p2->v,p2->info);p2=p2->nextarc;}printf("\n"); }*/ } //協助結構體,用來記錄邊的起始點,終點,權值信息 typedef struct end{char start;//邊的起點 char end;//變得終點 int w;//邊的權值 }Edge[100]; //將邊按照權值大小進行排序 void sort(Edge &E,ALgraph &R){char b;int num;int m=R.acrnum;for(int i=0;i<m ;i++){for(int j=0;j<m-i;j++){if(E[j+1].w<E[j].w){b=E[j+1].start;E[j+1].start=E[j].start;E[j].start=b;b=E[j+1].end;E[j+1].end=E[j].end;E[j].end=b;num=E[j+1].w;E[j+1].w=E[j].w;E[j].w=num;}}}} //找出兩結點的標號最大的那個 int max(int i,int j){if(i>j){return i;}else return j; } //找出兩結點的標號的小的那個 int min (int i,int j){if(i<j){return i;}else return j; } void minspantree_Kruskal(ALgraph &G,Edge &E){int u=0; //數組Edge的下標 int parent[G.vexnum+1];//標號用的數組 for(int i=1;i<=G.vexnum;i++){//將他們分成不同的集合 parent[i]=i;}ArNode *p1; //臨結點的指針 for(int i=1;i<=G.vexnum;i++){ //將每條邊的起點和終點,權值賦予結構體中EDGE中 p1=G.survice[i].firstarc; while(p1){ E[u].start=G.survice[i].data;E[u].end=p1->v;E[u].w=p1->info;u++;p1=p1->nextarc;}}sort(E,G); //將每條邊按照權值的大小排序int n=0;//要挑選出邊的下標 for(int i=0;i<=G.vexnum-1;i++){//邊的結構體下標是從零開始的 char head1 =E[n].start;//記錄選出邊的起始點 char end1 =E[n].end;//記錄選出邊的終點 if(parent[locate1(G,head1,G.vexnum)]!=parent[locate1(G,end1,G.vexnum)]){// 如果結點的標號不相等的話,將權值加上 sum+=E[n].w; int maxv=max(parent[locate1(G,head1,G.vexnum)],parent[locate1(G,end1,G.vexnum)]);//得到邊兩端結點標號的最大值 int minv=min(parent[locate1(G,head1,G.vexnum)],parent[locate1(G,end1,G.vexnum)]);//得到邊兩端結點標號的最小值 parent[locate1(G,head1,G.vexnum)]=minv; parent[locate1(G,end1,G.vexnum)]=minv;//他倆選出后成為一個集合,將標號都改為最小值 for (int j=1;j<=G.vexnum;j++){//將結點中所有標號都為邊兩端標號最大值的結點標號都改為最小值 if(parent[j]==maxv){parent[j]=minv;}}printf("<%c ,%c> \n",head1,end1); //輸出找出變的兩個結點 }n++;} printf("最小權值之和為:%d",sum); } int main (){ALgraph R;Edge E;//有關邊的結構體 creatUND(R);minspantree_Kruskal(R,E);return 0; }

總結

以上是生活随笔為你收集整理的克鲁斯卡尔算法建立最小生成树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。