数据结构:最小生成树(Kruskal)

来源:互联网 发布:apache index.html 编辑:程序博客网 时间:2024/06/06 03:27
算法思想:假设N = { V, {E} }是连通网,则令最小生成树的初始状态为只有n个顶点而无边的非连通图
T = { V, {} },图中每个顶点自成一个连通分量。在E中选择
代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。依次类推,直到T中所有顶点都在同一连通分量上为止。

此算法的
FindInUFS函数由边数e决定,时间复杂度为O(loge),而外面有一个for循环e次,所以Kruskal算法的时间复杂度为O(eloge)。

对比Prim算法与Kruskal算法,Kruskal算法主要针对边来展开,边数少时效率会很高,所以对稀疏图有很大的优势。而Prim算法对于稠密图,即边数非常多的情况会更好一些。



#include <iostream>#include <string>#include <queue>#include <deque>using namespace std;#define MAXSIZE 10  //顶点最大个数typedef string VertexType; //顶点类型typedef int EdgeType;  //权值类型,有向图(0,1),无向图(权值,无穷大)#define INFINITY 0xfffftypedef struct  {VertexType Vexs[MAXSIZE];  //顶点向量EdgeType arcs[MAXSIZE][MAXSIZE]; //邻接矩阵,可看作为边表int iVexNum;  //顶点个数int iArcNum;  //边数}MGraph;#define SUCCESS 1#define UNSUCCESS 0typedef int Status;//由顶点值得到顶点索引int GetIndexByVertexVal( const MGraph& MG, VertexType val ){for ( int i = 0; i < MG.iVexNum; ++i ){if ( val == MG.Vexs[i] )return i;}return -1;}//创建无向图Status CreateGraph( MGraph& MG ){cout << "输入顶点个数以及边数:";cin >> MG.iVexNum >> MG.iArcNum;cout << "请输入" << MG.iVexNum << "个顶点:";for ( int i = 0; i < MG.iVexNum; ++i ){cin >> MG.Vexs[i];}for ( int i = 0; i < MG.iVexNum; ++i ){for ( int j = 0; j < MG.iVexNum; ++j ){MG.arcs[i][j] = INFINITY;}}cout << "请输入由两点构成的边及其权值:";for ( int i = 0; i < MG.iArcNum; ++i ){VertexType first;VertexType second;EdgeType weight;cin >> first >> second >> weight;int m = GetIndexByVertexVal( MG, first );int n = GetIndexByVertexVal( MG, second ); if ( m == -1 || n == -1 )return UNSUCCESS;MG.arcs[m][n] = MG.arcs[n][m] = weight;}return SUCCESS;}typedef struct  {int begin; int end;int weight;  //权值}Edge;//在并查集中查找int FindInUFS( int* parent, int k ){while ( parent[k] != k ){k = parent[k];}return k;}//克鲁斯卡尔算法求最小生成树void MiniSpanTree_Kruskal( const MGraph& G ){//转换为边集数组Edge* pEdge = new Edge[G.iArcNum];memset( pEdge, 0, G.iArcNum*sizeof(Edge) );int m = 0;for ( int i = 1; i < G.iVexNum; ++i ){int k = i - 1;for ( int j = 0; j <= k; ++j ){if ( G.arcs[i][j] != INFINITY ){pEdge[m].begin = i;pEdge[m].end = j;pEdge[m].weight = G.arcs[i][j];++m;}}}//按权值从小到大进行排序for ( int i = 1; i < G.iArcNum-1; ++i ){bool flag = false;for ( int j = 0; j < G.iArcNum - i; ++j ){if ( pEdge[j].weight > pEdge[j+1].weight ){int temp;temp = pEdge[j].begin;pEdge[j].begin = pEdge[j+1].begin;pEdge[j+1].begin = temp;temp = pEdge[j].end;pEdge[j].end = pEdge[j+1].end;pEdge[j+1].end = temp;temp = pEdge[j].weight;pEdge[j].weight = pEdge[j+1].weight;pEdge[j+1].weight = temp;flag = true;}}if ( !flag ){break;}}//并查集int* parent = new int[G.iArcNum];for ( int i = 0; i < G.iArcNum; ++i ){parent[i] = i;}for ( int i = 0; i < G.iArcNum; ++i ){int m = FindInUFS( parent, pEdge[i].begin );int n = FindInUFS( parent, pEdge[i].end );if ( m != n ){cout << "(" << pEdge[i].begin << "," << pEdge[i].end << "," << pEdge[i].weight << ")" << endl;parent[m] = n;}}if ( !pEdge ){delete[] pEdge;pEdge = NULL;}if ( !parent ){delete[] parent;parent = NULL;}}int main(){MGraph MG;CreateGraph( MG );//克鲁斯卡尔算法求最小生成树cout << "普里姆算法求解最小生成数:" << endl;MiniSpanTree_Kruskal( MG );cout << endl; return 0;} 


0 0
原创粉丝点击