构造最小生成树Prim算法和Kruskal算法
2018-02-09 00:03
239 查看
1.构造最小生成树的 Prim 算法
假设 G=(V,E)为一网图,其中 V 为网图中所有顶点的集合,E 为网图中所有带权边的集合。设置两个新的集合 U 和 T,其中集合 U 用于存放 G 的最小生成树中的顶点,集合 T存放 G 的最小生成树中的边。令集合 U 的初值为 U={u1}(假设构造最小生成树时,从顶点u1 出发),集合 T 的初值为 T={}。
Prim 算法的思想是:从所有 u∈U,v∈V-U 的边中,选取具有最小权值的边(u,v),将顶点 v 加入集合 U 中,将边(u,v)加入集合 T 中,如此不断重复,直到 U=V 时,最小生成树构造完毕,这时集合 T 中包含了最小生成树的所有边。
Prim 算法可用下述过程描述,其中用 Wuv 表示顶点 u 与顶点 v 边上的权值。
(1)U={u1},T={};
(2)while (U≠V)do
(u,v)=min{Wuv ;u∈U,v∈V-U }
T=T+{(u,v)}
U=U+{v}
(3)结束。
Prim 算法的时间复杂度为 O(n^2 ),与网中的边数无关,因此适用于求边稠密的网的最小生成树。
2.构造最小生成树的 Kruskal 算法
Kruskal 算法是一种按照网中边的权值递增的顺序构造最小生成树的方法。其基本思想是:设无向连通网为 G=(V,E),令 G 的最小生成树为 T,其初态为 T=(V,{}),即开始时,最小生成树 T 由图 G 中的 n 个顶点构成,顶点之间没有一条边,这样 T 中各顶点各自构成一个连通分量。然后,按照边的权值由小到大的顺序,考察 G 的边集 E 中的各条边。若被考察的边的两个顶点属于 T 的两个不同的连通分量,则将此边作为最小生成树的边加入到T 中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当 T 中的连通分量个数为 1 时,此连通分量便为 G 的一棵最小生成树。
Kruskal 算法需对 e 条边按权值进行排序,时间复杂度为 O(eloge)(e 为网中边的数目),因此适用于求边稀疏的网的最小生成树。
C++代码实现Prim和kruskal算法:
2
3
4
假设 G=(V,E)为一网图,其中 V 为网图中所有顶点的集合,E 为网图中所有带权边的集合。设置两个新的集合 U 和 T,其中集合 U 用于存放 G 的最小生成树中的顶点,集合 T存放 G 的最小生成树中的边。令集合 U 的初值为 U={u1}(假设构造最小生成树时,从顶点u1 出发),集合 T 的初值为 T={}。
Prim 算法的思想是:从所有 u∈U,v∈V-U 的边中,选取具有最小权值的边(u,v),将顶点 v 加入集合 U 中,将边(u,v)加入集合 T 中,如此不断重复,直到 U=V 时,最小生成树构造完毕,这时集合 T 中包含了最小生成树的所有边。
Prim 算法可用下述过程描述,其中用 Wuv 表示顶点 u 与顶点 v 边上的权值。
(1)U={u1},T={};
(2)while (U≠V)do
(u,v)=min{Wuv ;u∈U,v∈V-U }
T=T+{(u,v)}
U=U+{v}
(3)结束。
Prim 算法的时间复杂度为 O(n^2 ),与网中的边数无关,因此适用于求边稠密的网的最小生成树。
2.构造最小生成树的 Kruskal 算法
Kruskal 算法是一种按照网中边的权值递增的顺序构造最小生成树的方法。其基本思想是:设无向连通网为 G=(V,E),令 G 的最小生成树为 T,其初态为 T=(V,{}),即开始时,最小生成树 T 由图 G 中的 n 个顶点构成,顶点之间没有一条边,这样 T 中各顶点各自构成一个连通分量。然后,按照边的权值由小到大的顺序,考察 G 的边集 E 中的各条边。若被考察的边的两个顶点属于 T 的两个不同的连通分量,则将此边作为最小生成树的边加入到T 中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当 T 中的连通分量个数为 1 时,此连通分量便为 G 的一棵最小生成树。
Kruskal 算法需对 e 条边按权值进行排序,时间复杂度为 O(eloge)(e 为网中边的数目),因此适用于求边稀疏的网的最小生成树。
C++代码实现Prim和kruskal算法:
#include <iostream> #include <vector> #include <queue> #include <algorithm> using namespace std; #define INFINITE 0xFFFFFFFF #define VertexData unsigned int //顶点数据 #define UINT unsigned int #define vexCounts 6 //顶点数量 char vextex[] = { 'A', 'B', 'C', 'D', 'E', 'F' }; struct node { VertexData data; unsigned int lowestcost; }closedge[vexCounts]; //Prim算法中的辅助信息 typedef struct { VertexData u; VertexData v; unsigned int cost; //边的代价 }Arc; //原始图的边信息 void AdjMatrix(unsigned int adjMat[][vexCounts]) //邻接矩阵表示法 { for (int i = 0; i < vexCounts; i++) //初始化邻接矩阵 for (int j = 0; j < vexCounts; j++) { adjMat[i][j] = INFINITE; } adjMat[0][1] = 6; adjMat[0][2] = 1; adjMat[0][3] = 5; adjMat[1][0] = 6; adjMat[1][2] = 5; adjMat[1][4] = 3; adjMat[2][0] = 1; adjMat[2][1] = 5; adjMat[2][3] = 5; adjMat[2][4] = 6; adjMat[2][5] = 4; adjMat[3][0] = 5; adjMat[3][2] = 5; adjMat[3][5] = 2; adjMat[4][1] = 3; adjMat[4][2] = 6; adjMat[4][5] = 6; adjMat[5][2] = 4; adjMat[5][3] = 2; adjMat[5][4] = 6; } int Minmum(struct node * closedge) //返回最小代价边 { unsigned int min = INFINITE; int index = -1; for (int i = 0; i < vexCounts;i++) { if (closedge[i].lowestcost < min && closedge[i].lowestcost !=0) { min = closedge[i].lowestcost; index = i; } } return index; } void MiniSpanTree_Prim(unsigned int adjMat[][vexCounts], VertexData s) { for (int i = 0; i < vexCounts;i++) { closedge[i].lowestcost = INFINITE; } closedge[s].data = s; //从顶点s开始 closedge[s].lowestcost = 0; for (int i = 0; i < vexCounts;i++) //初始化辅助数组 { if (i != s) { closedge[i].data = s; closedge[i].lowestcost = adjMat[s][i]; } } for (int e = 1; e <= vexCounts -1; e++) //n-1条边时退出 { int k = Minmum(closedge); //选择最小代价边 cout << vextex[closedge[k].data] << "--" << vextex[k] << endl;//加入到最小生成树 closedge[k].lowestcost = 0; //代价置为0 for (int i = 0; i < vexCounts;i++) //更新v中顶点最小代价边信息 { if ( adjMat[k][i] < closedge[i].lowestcost) { closedge[i].data = k; closedge[i].lowestcost = adjMat[k][i]; } } } } void ReadArc(unsigned int adjMat[][vexCounts],vector<Arc> &vertexArc) //保存图的边代价信息 { Arc * temp = NULL; for (unsigned int i = 0; i < vexCounts;i++) { for (unsigned int j = 0; j < i; j++) { if (adjMat[i][j]!=INFINITE) { temp = new Arc; temp->u = i; temp->v = j; temp->cost = adjMat[i][j]; vertexArc.push_back(*temp); } } } } bool compare(Arc A, Arc B) { return A.cost < B.cost ? true : false; } bool FindTree(VertexData u, VertexData v,vector<vector<VertexData> > &Tree) { unsigned int index_u = INFINITE; unsigned int index_v = INFINITE; for (unsigned int i = 0; i < Tree.size();i++) //检查u,v分别属于哪颗树 { if (find(Tree[i].begin(), Tree[i].end(), u) != Tree[i].end()) index_u = i; if (find(Tree[i].begin(), Tree[i].end(), v) != Tree[i].end()) index_v = i; } if (index_u != index_v) //u,v不在一颗树上,合并两颗树 { for (unsigned int i = 0; i < Tree[index_v].size();i++) { Tree[index_u].push_back(Tree[index_v][i]); } Tree[index_v].clear(); return true; } return false; } void MiniSpanTree_Kruskal(unsigned int adjMat[][vexCounts]) { vector<Arc> vertexArc; ReadArc(adjMat, vertexArc);//读取边信息 sort(vertexArc.begin(), vertexArc.end(), compare);//边按从小到大排序 vector<vector<VertexData> > Tree(vexCounts); //6棵独立树 for (unsigned int i = 0; i < vexCounts; i++) { Tree[i].push_back(i); //初始化6棵独立树的信息 } for (unsigned int i = 0; i < vertexArc.size(); i++)//依次从小到大取最小代价边 { VertexData u = vertexArc[i].u; VertexData v = vertexArc[i].v; if (FindTree(u, v, Tree))//检查此边的两个顶点是否在一颗树内 { cout << vextex[u] << "---" << vextex[v] << endl;//把此边加入到最小生成树中 } } } int main() { unsigned int adjMat[vexCounts][vexCounts] = { 0 }; AdjMatrix(adjMat); //邻接矩阵 cout << "Prim :" << endl; MiniSpanTree_Prim(adjMat,0); //Prim算法,从顶点0开始. cout << "-------------" << endl << "Kruskal:" << endl; MiniSpanTree_Kruskal(adjMat);//Kruskal算法 return 0; }1
2
3
4
相关文章推荐
- 图论中最小生成树构造算法之Prim算法和Kruskal算法
- 最小生成树构造算法--Prim算法,Kruskal算法(C语言)
- Prim算法和Kruskal算法构造最小生成树
- 最小生成树-Prim算法和Kruskal算法
- 最小生成树-Prim算法和Kruskal算法(转)
- 最小生成树——Kruskal算法 和 Prim算法
- 最小生成树-Prim算法和Kruskal算法
- 图论算法:最小生成树——Prim算法和Kruskal算法C++实现
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- Kruskal算法构造最小生成树
- 最小生成树-Prim算法和Kruskal算法
- 最小生成树问题中Kruskal算法和Prim算法的C语言实现
- 最小生成树之Prim算法,Kruskal算法
- 【数据结构】最小生成树之prim算法和kruskal算法
- 最小生成树-Prim算法和Kruskal算法
- hdu 1162 Eddy's picture (Kruskal算法,prim算法,最小生成树)
- 求最小生成树——Kruskal算法和Prim算法
- 无向网最小生成树 prim算法 和 kruskal算法
- 最小生成树-Prim算法和Kruskal算法