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算法:
当前关联vi的轻边权值
该边依附的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 100 class 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; //正确输入用关联矩阵来存储一个图,并且定义closeedge Graph 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; else G.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)