#include <iostream>
using namespace std;
#define max_vertex_num 20
int vex_num;//顶点个数
char v[max_vertex_num];//存储顶点
int arcs[max_vertex_num][max_vertex_num];//存储权值
void Initialization();//图的初始化
int LocateVex(char u);//定位顶点u,返回顶点在一维数组v中的下标
void InsertVex(char s);//插入顶点
void SetWeight(int u,int v,int w);//设置权值
void SetWeight(char u,char v,int w);//设置权值
void Kruskal();//算法
int find(int x,int set[],int vex_num)
{//初始时,每个顶点的类标号就是本身的标号
int y;
y=x;
while(1)
{//找到x所在集合的根节点
if(set[y]==y)
{//若顶点的类标号是本身,则其是树根
break;
}
else
{
y=set[y];
}
}
//从x开始向根,将路径上的结点的双亲直接设置为y
int r;
while(1)
{
if(set[x]==y)
break;
r=set[x];
set[x]=y;
x=r;
}
return y;
}
void merge(int x,int y,int set[],int vex_num)
{//x、y是两个集合的树根。现在要合并在一起
set[x]=y;
}
int main(int argc, char* argv[])
{
Initialization();//图的初始化
//下面通过插入顶点和插入边,构造图
InsertVex('a');InsertVex('b');InsertVex('c');
InsertVex('d');InsertVex('e');InsertVex('f');
SetWeight('a','b',6);
SetWeight('a','c',1);
SetWeight('a','d',5);
SetWeight('b','c',5);
SetWeight('b','e',3);
SetWeight('c','d',5);
SetWeight('c','e',6);
SetWeight('c','f',4);
SetWeight('d','f',2);
SetWeight('e','f',6);
//调用Prim算法,生成最小生成树
Kruskal();
return 0;
}
void Initialization()
{//图的初始化
vex_num=0;//开始时,顶点个数为0
for(int i=1;i<max_vertex_num;i++)
for(int j=i;j<max_vertex_num;j++)
arcs[i][j]=arcs[j][i]=99999;//表示无穷大
}
void InsertVex(char s)
{//插入一个顶点
vex_num++;
v[vex_num]=s;//vex_num同时代表最后一个顶点在数组v中的下标
}
//
int LocateVex(char u)
{//定位顶点u对应的下标
for(int i=1;i<=vex_num;i++)
{ if(v[i]==u) return i; }
return 0;
}
void SetWeight(int u, int v, int w)
{//设置边上的权值
arcs[u][v]=arcs[v][u]=w;
}
void SetWeight(char u, char v, int w)
{//设置边上的权值
SetWeight(LocateVex(u),LocateVex(v),w);
}
void Kruskal()
{
struct edge
{
int u;
int v;
int length;
};
edge L[max_vertex_num];//数组L,用来存储各条边
int index=0;
int i,j;
for(i=1;i<=vex_num;i++)
{
for(j=i;j<=vex_num;j++)
{
if(arcs[i][j]!=99999)
{
index++;
L[index].u=i;
L[index].v=j;
L[index].length=arcs[i][j];
}
}
}
//下面要对L中的边按照length从小到大排序
//简单选择排序
for(i=1;i<index;i++)
{
for(j=i+1;j<=index;j++)
{
if(L[j].length<L[i].length)
{
edge t;
t=L[j];
L[j]=L[i];
L[i]=t;
}
}
}
//输出排好序的边,测试排序程序
//for(i=1;i<=index;i++)
// cout<<L[i].u<<"-->"<<L[i].v<<" "<<L[i].length<<endl;
//
int set[max_vertex_num];
//初始时,每个顶点自成一个集合
for(i=1;i<=vex_num;i++)
set[i]=i;
int edge_nums=0;//选出到最小生成树中的边的条数
i=1;//从边集合的第一条边开始取
while(edge_nums<vex_num-1)
{
int x,y;
//优先选取权值最小的边
x=find(L[i].u,set,vex_num);//寻找顶点u的类别
y=find(L[i].v,set,vex_num);//寻找顶点v的类别
if(x!=y)
{//如果边的两个顶点还不属于同一个集合,则让他们同属一个集合
cout<<"("<<v[x]<<" , "<<v[y]<<")"<<endl;
edge_nums++;
//合并顶点x和y的类别
merge(x,y,set,vex_num);
}
i++;
}
}