图Graph--最小生成树
生活随笔
收集整理的這篇文章主要介紹了
图Graph--最小生成树
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- 1.概念
- 2.構(gòu)造最小生成樹Prim算法
- 3.構(gòu)造最小生成樹Kruskal算法
1.概念
- 對圖運用不同的遍歷方法就可能得到圖的不同遍歷順序,每一種遍歷順序?qū)?yīng)于一棵生成樹
- 對于無向連通圖,所有的生成樹中必有一棵樹的所有邊的權(quán)的總和最小的,稱之為最小生成樹(Minimum cost spanning tree)
練習(xí)題:
LeetCode 1135. 最低成本聯(lián)通所有城市(最小生成樹+排序+并查集)
LeetCode 1489. 找到最小生成樹里的關(guān)鍵邊和偽關(guān)鍵邊(并查集+kruskal最小生成樹)
2.構(gòu)造最小生成樹Prim算法
從某點出發(fā)(該點加入集合U),找到跟它相連接的點,從中取出權(quán)值最小的,加入集合U,對這個集合U,查找與U內(nèi)所有的點相連的點的權(quán)值,取權(quán)值最小的點,加入集合U,直到所有點加入到U。
struct CloseEdge //最短的邊 {int startV;int endV;int minWeight; //最小的權(quán)值bool operator < (const CloseEdge &s) const{//符號重載return minWeight < s.minWeight;} }; //----------prim最小生成樹--------------- void MiniSpanTree_Prim(char ch) {int s = findPos(ch);if(s >= v)return;cout << "從 " << ch << " 開始的Prim最小生成樹:" << endl;int i, j, k, x, w, minid, sum = 0;for(i = 0; i < v; ++i)visited[i] = 0;//訪問標志置0visited[s] = 1;vector<int> q;vector<int>::iterator it;q.push_back(s);for(i = 0; i < v-1; ++i){for(it = q.begin(),x = 0; it != q.end(); ++it,++x){w = MaxValue;for(j = 0; j < v; ++j){if (!visited[j] && ew[*it][j] < w){w = ew[*it][j];minid = j;//記錄較小的權(quán)的序號為k}}close_edge[x].minWeight = w;close_edge[x].startV = *it;close_edge[x].endV = minid;}sort(close_edge,close_edge+x);visited[close_edge[0].endV] = 1;cout << vertex[close_edge[0].startV] << "-" << vertex[close_edge[0].endV] << " 權(quán)值 " << close_edge[0].minWeight << endl;sum += close_edge[0].minWeight;q.push_back(close_edge[0].endV);}cout << "最小生成樹權(quán)重總和為:" << sum << endl;}我這個程序比較好理解,但是復(fù)雜度n3。書上的程序?qū)懛ㄊ莕2。
int main() { //------------以下測試Prim最小生成樹------------------ // A -40- B -50- C // 30| \10 5| 20| // D -35- E -45- F // 10| 55| 10| // I -15- G -25- H //請輸入以下數(shù)據(jù)生成上面的圖 //A B C D E F G H I A B 40 B C 50 A D 30 B E 5 C F 20 D E 35 E F 45 E G 55 F H 10 G H 25 A E 10 D I 10 I G 15arrGraph bg(9,13); //9個頂點,13條邊,默認生成無向圖bg.creatGraph();bg.printArrOfGraph();bg.MiniSpanTree_Prim('A');bg.MiniSpanTree_Prim('I');//從任一點出發(fā),最小花費都一樣return 0; }完整代碼:https://github.com/hitskyer/course/blob/master/dataAlgorithm/chenmingming/graph/arrayGraph.cpp
從任意一點出發(fā)最小生成樹的最小代價總和都相等。
看了別人的代碼,調(diào)試后,明白了n2復(fù)雜度的Prim算法
void MiniSpanTree_Prim_O_n2(char ch) {int s = findPos(ch);if (s >= v)return;cout << "從 " << ch << " 開始的Prim最小生成樹:" << endl;int i, j, k, minweight, sum = 0;int adjvex[v]; //保存頂點下標int lowcost[v]; //保存相關(guān)頂點見的權(quán)值lowcost[s] = 0; //=0,加入了生成樹adjvex[s] = s; //起點下標為自己for(i = 0; i < v; ++i){if(i == s)continue;lowcost[i] = ew[s][i];//將s起點與其他點的權(quán)值初始化adjvex[i] = s;//到達i的前一個點初始化為起點}for(i = 0; i < v-1; ++i){minweight = MaxValue;for(j = 0, k = 0; j < v; ++j){if(lowcost[j] != 0 && lowcost[j] < minweight)//未加入生成樹的,且j點的比較小{minweight = lowcost[j];//更新最小值k = j;//下標記錄入k}}cout << vertex[adjvex[k]] << "-" << vertex[k] << " 權(quán)值 " << ew[adjvex[k]][k] << endl;lowcost[k] = 0;//最小的權(quán)值點k加入生成樹sum += ew[adjvex[k]][k];for(j = 0; j < v; ++j){if(lowcost[j] != 0 && ew[k][j] < lowcost[j])//k加入生成樹后,對k周圍的權(quán)與最小權(quán)l(xiāng)owcost比較{lowcost[j] = ew[k][j];//更小的權(quán)更新lowcost數(shù)組adjvex[j] = k;//并記錄j的前一位是k}}}cout << "最小生成樹權(quán)重總和為:" << sum << endl; }3.構(gòu)造最小生成樹Kruskal算法
該算法思路是從邊(權(quán)重)出發(fā)考慮,取最小的權(quán)出來,若該邊不會造成回路就加入生成樹,然后次最小,循環(huán)下去
//----------Kruskal最小生成樹--------------- void MiniSpanTree_Kruskal() {cout << "Kruskal最小生成樹:" << endl;int i, j, k = 0, sum = 0;CloseEdge edges[MaxEdgeNum]; //邊數(shù)據(jù)集for(i = 0; i < v; ++i) //把邊信息輸入到edges數(shù)組for(j = 0; j < v; ++j)if(ew[i][j] != MaxValue && i > j)//無向圖,i>j 矩陣中一半就可獲取全部信息{edges[k].startV = i;edges[k].endV = j;edges[k].minWeight = ew[i][j];k++;}sort(edges,edges+k);//邊排序int parent[e]; //作用,判斷邊與邊是否形成回路int vf1, vf2;for(i = 0; i < k; ++i)parent[i] = 0;for(i = 0; i < k; ++i){vf1 = Find(parent, edges[i].startV);vf2 = Find(parent, edges[i].endV);if(vf1 != vf2)//沒有回路,可以選入生成樹{parent[vf2] = vf1;cout << vertex[edges[i].startV] << "-" << vertex[edges[i].endV]<< " 權(quán)重 " << edges[i].minWeight << endl;sum += edges[i].minWeight;}}cout << "最小生成樹權(quán)重總和為:" << sum << endl; } int Find(int* parent, int v) {int t = v;while(parent[t] > 0)t = parent[t];return t; }總結(jié)
以上是生活随笔為你收集整理的图Graph--最小生成树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python求矩阵的秩_Python 实
- 下一篇: LeetCode 1094. 拼车