用Prim和Kruskal算法实现图的最小生成树

来源:互联网 发布:淘宝9.9的鼠标垫 编辑:程序博客网 时间:2024/06/04 17:52

1.最小生成树的概念

  

最小生成树   由一个网络生成的各边的权数总和最小的生成树,记为MST(Minimum Cost Spanning Tree)。

MST性质   设N=(V,{E})是一个连通的网络,U是V的真子集,若边(u,v)[uÎU,vÎV-U]是E中所有一个端点在U内,一个端点不在U内的边中权值最小的一条边(轻边),则一定存在G的一棵生成树包括此边。


1.Prim算法:

•主:带权邻接矩阵G.arcs[n][n]—记录图
•辅:数组closedge[i](i=0..n-1)—记录候选边
–lowcost

    当前关联vi的轻边权值

–adjvex

    该边依附的U集合中的顶点下标

    示例初值:    0  1   2   3  4   5

     lowcost        0  6   1  5   µ  µ

      adjvex        0  0   0   0  0   0

算法步骤

1)初始化closedge[j](j=0..n-1)                              O(n)

2)重复n-1次以下操作:

  2.1)在closedge[j](j=0..n-1)中选择最小且非0的  lowcost,记录其j 值(设为k)和相应的adjvex;                 O(n2)

  2.2)输出该边(adjvex,k);                                  O(n)

  2.3)顶点k并入U集:closedge[k].lowcost=0; O(n)

  2.4)调整候选边集closedge[j](j=0..n-1):           O(n2)

   若G.arcs[k][j]< closedge[j].lowcost,

   则更改closedge[j]:adjvex=k,lowcost=G.arcs[k][j]

                                                                              O(n2)

C++代码

#include<iostream>#include<stdlib.h>using namespace std;#define MAX 100class block {public:int lowcost;int adjvex;  //关联的顶点};class Graph {public:char vertex_num[MAX];  //顶点信息对应的矩阵的编号int e[MAX][MAX];int vexnum;   //图的顶点数目int edgenum;  //图的边的数目     };void Prim(Graph G);int findmin(block*, int);int main(){int i, j;//正确输入用关联矩阵来存储一个图,并且定义closeedgeGraph G;cout<< "请输入无向图的顶点数目和图的边的数目\n";cin >> G.vexnum;cin >> G.edgenum;//初始化关联矩阵for(i=1;i<=G.vexnum;i++)for (j = 1; j <= G.vexnum; j++){if (i == j)G.e[i][j] = 0;elseG.e[i][j] = 99999;}cout << "请输入各顶点的信息\n";for (i = 1; i <= G.vexnum; i++){cin >> G.vertex_num[i];}cout << "请输入各边的相关信息\n";int j1,j2;char vert1, vert2;int weight;for (i = 1; i <= G.edgenum; i++){cin >> vert1;cin >> vert2;cin >> weight;for (j1 = 1; G.vertex_num[j1] != vert1; j1++);for (j2 = 1; G.vertex_num[j2] != vert2; j2++);G.e[j1][j2] = weight;G.e[j2][j1] = weight;}/*//存储检查for (i = 1; i <= G.vexnum; i++){for (j = 1; j <= G.vexnum; j++)cout << G.e[i][j] << " ";cout << "\n";}*/Prim(G);system("pause");}void Prim(Graph G){block closeedge[MAX];//先初始化closeedge数组,用e[][]的某一行(我选的是第一行)进行初始化//然后选取第一行中的最小权值连接的顶点,输出信息,加入到U集合中,(即将lowcost=0)//并且用该顶点去疏散其他还未进入U集合的点,如此往复int i, k, j;for (i = 1; i <= G.vexnum; i++){closeedge[i].adjvex = 1;closeedge[i].lowcost = G.e[1][i];}cout << "从1号顶点开始\n";for (i = 2; i <= G.vexnum; i++){k = findmin(closeedge,G.vexnum);closeedge[k].lowcost = 0; //加入U集合cout << "下一个顶点是" << G.vertex_num[k]<<" ";cout<<"对应的边的权值是" << G.e[k][closeedge[k].adjvex]<<"\n";for (j = 1; j <= G.vexnum; j++){if (G.e[k][j] < closeedge[j].lowcost){closeedge[j].lowcost = G.e[k][j];closeedge[j].adjvex = k;}}}}int findmin(block*close,int vexnum){int min = 1, lows = 99999;int i;for (i = 1; i <= vexnum; i++){if (close[i].lowcost < lows&&close[i].lowcost != 0){lows = close[i].lowcost;min = i;}}return min;}

2.Kruskal算法

1)初始化T:顶点集=所有顶点,每个独立的顶点作为一棵树,边集=ø;                                                        O(n)

2)依权值递增序对图G的边排序,结果为E[0..e-1]    O(elge)

3)依次检测E中的各边(u,v):                                    O(elge)

     3.1) 若u和v分属于T中两棵不同的树,则将该边加入T,并合并u和v分属的两棵树

     3.2) 若T中所有顶点尚未属于一棵树,转3)


原创粉丝点击