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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

最小代价生成树Prim/Kruskal(c/c++)

發布時間:2025/6/17 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最小代价生成树Prim/Kruskal(c/c++) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

常用的求最小代價生成樹的方法有兩種:Prim算法和Kruskal算法,這兩種算法都是貪心算法的應用,

Prim算法

在一個無向帶權圖中求得最小生成樹得思路是:從a頂點出發,將a放入u集合(表示已選),找與u集合中所有點連接的權值最小的邊(此時只有a結點),假設該邊連接a和b結點,b結點被選定放入u集合,查找與u集合中所有點連接的權值最小的邊(此時有a,b結點),通過改變找到c結點,c被選定放入u集合中…當所有結點都被選中時,最小生成樹建成了。故Prim可看做為‘加點’的算法。

輔助結構
typedef struct {int adjvex;//相連接的頂點int lowcost;//表示權值 }st; st closeEdge[maxSize]; closeEdge[i].adjvex=k;//k為在集合中的頂點 closeEdge[i[.lowcost=0;

i頂點與在集合中的k頂點相鄰接。i頂點的lowcost為0,表示將i頂點被選中加入u集合

代碼如下

用鄰接矩陣存儲圖,將邊上的權值存入矩陣中,圖中不連接的邊在矩陣中為INT_MAX,自身之間的連接也存為INT_MAX

void miniSpanTree(mGraph& G, int u) {//從頂點u出發構造G的最小代價生成樹int i, j, min;for (i = 0; i < G.vexnum; i++)if (i != u)closeEdge[i]= { u, G.arc[i][u]};//初始化與u相連所有頂點間的權值closeEdge[u].lowcost = 0;//將u加入到已選集合中for (j = 1; j < G.vexnum; j++)//僅起到循環G.vexnum-1次的作用{int minValue =INT_MAX;for (i = 0; i < G.vexnum; i++)if (closeEdge[i].lowcost != 0){if (minValue > closeEdge[i].lowcost){minValue = closeEdge[i].lowcost;min = i;}}std::cout << "選定結點: "<<G.vex[min] << " 權值: " << closeEdge[min].lowcost << '\n';closeEdge[min].lowcost = 0;//將min頂點加入已選集合中for (i = 0; i < G.vexnum; i++){if (closeEdge[i].lowcost != 0){if (closeEdge[i].lowcost>G.arc[min][i])closeEdge[i] = { min, G.arc[min][i] };//i與集合中的min相連,因為它們的權值更小}}} }
完整示例

輸入圖如下:6個頂點,10條邊

對該圖用prim算法進行最小代價生成樹構造代碼如下:

#include<iostream> //#include<climits> #define maxSize 6//頂點數目 #define MAX 10//邊的個數 //鄰接矩陣 typedef struct {int vexnum, arcnum;//頂點數和邊數char vex[maxSize];//頂點信息(字符)int arc[maxSize][maxSize];//二維數組(存儲邊上的信息) }mGraph;typedef struct {int adjvex;//相連接的頂點int lowcost;//表示權值 }st; st closeEdge[maxSize];void miniSpanTree(mGraph& G, int u);//u頂點的序號 int main() {using namespace std;mGraph G;//鄰接矩陣存儲圖并進行初始化G.vexnum = maxSize;G.arcnum = MAX;char vexData[maxSize] = { 'a', 'b', 'c', 'd', 'e','f'};//頂點信息int arcData[MAX][3] = { { 0, 1, 6 }, { 0, 2, 1 }, { 0, 3, 5 }, { 1, 2, 5 }, { 2, 3, 5 },{ 1, 4, 3 }, { 2, 4, 6 }, { 2, 5, 4 }, { 3, 5, 2 }, { 4, 5, 6 } };//連接的邊及權值int i, j;for (i = 0; i < G.vexnum; ++i){G.vex[i] = vexData[i];for (j = 0; j < G.vexnum; j++)G.arc[i][j] = INT_MAX;}for (i = 0; i < G.arcnum; i++)G.arc[arcData[i][0]][arcData[i][1]] = G.arc[arcData[i][1]][arcData[i][0]] = arcData[i][2];//初始化完畢cout << "Prim 最小代價生成樹: " << endl;cout << "自頂點" << G.vex[0] << "開始:\n";miniSpanTree(G,0);//從第一個頂點構造最小生成樹cout << endl;return 0; } void miniSpanTree(mGraph& G, int u) {//從頂點u出發構造G的最小代價生成樹int i, j, min;for (i = 0; i < G.vexnum; i++)if (i != u)closeEdge[i]= { u, G.arc[i][u]};//初始化與u相連所有頂點間的權值closeEdge[u].lowcost = 0;//將u加入到已選集合中for (j = 1; j < G.vexnum; j++){int minValue =INT_MAX;for (i = 0; i < G.vexnum; i++)if (closeEdge[i].lowcost != 0){if (minValue > closeEdge[i].lowcost){minValue = closeEdge[i].lowcost;min = i;}}std::cout << "選定結點: "<<G.vex[min] << " 權值: " << closeEdge[min].lowcost << '\n';closeEdge[min].lowcost = 0;//將min頂點加入已選集合中for (i = 0; i < G.vexnum; i++){if (closeEdge[i].lowcost != 0){if (closeEdge[i].lowcost>G.arc[min][i])closeEdge[i] = { min, G.arc[min][i] };//i與集合中的min相連,因為它們的權值更小}}} }

輸出結果如下:

Kruskal算法

Kruskal算法可看作為‘加邊’來得到最小生成樹。它的思路為:
1,找到所有邊中代價(權值)最小的邊,加入u集合中
2,判定該邊所關聯的兩個頂點是否在同一個分量中(可以用DFS在集合u中來判斷,當一次DFS可以成功查找到,那么兩個頂點在同一個分量中)如果兩個頂點已經在同一個分量中,那么該邊被舍棄,否則該邊被加入到所選集合u中
3,再找代價最小的邊,再判定…
對于下圖:

先找到a-c邊,然后是d-f邊,再是b-e邊,接下來是c-f邊,如果當找到a-d邊時,因為在集合u中a頂點與d頂點已經在同一個連通分量中了,舍棄a-d邊,重新查找…

總結

以上是生活随笔為你收集整理的最小代价生成树Prim/Kruskal(c/c++)的全部內容,希望文章能夠幫你解決所遇到的問題。

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