您的位置:首页 > 理论基础 > 数据结构算法

邻接矩阵实现克鲁斯卡尔算法

2016-08-03 01:10 330 查看
//主要源代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 999999
#define MAX_NAME 3
#define VERTEX_MAX_NUM 100
typedef char VertexType[MAX_NAME];
typedef int VRType;
typedef struct {    //建立邻接矩阵
int weight;
}adjMatrix[VERTEX_MAX_NUM][VERTEX_MAX_NUM];
struct MGraph{
VertexType vex[VERTEX_MAX_NUM];//建立顶点向量
adjMatrix arcs;  //图中的邻接矩阵
int vrtnum,arcnum;//顶点,弧的个数
};
typedef struct Sort{
int x,y,w;
}weightValue[VERTEX_MAX_NUM*VERTEX_MAX_NUM];
typedef struct VRTFather{
int fa;
}Father[VERTEX_MAX_NUM];
int LocateVex(MGraph G,VertexType u){
int i;
for( i=0;i<G.vrtnum;i++)
if(strcmp(u,G.vex[i])==0)
return i;
return -1;
}
void creatMGraph(MGraph &G){
int i,j,w;
VertexType va,vb;
printf("请输入无向图G的顶点数、边数:");
scanf("%d %d",&G.vrtnum,&G.arcnum);
printf("请输入%d个顶点的值:\n",G.vrtnum);
for(i=0;i<G.vrtnum;i++) //构造顶点向量,(其实就是将顶点的名字换成数字)
scanf("%s",G.vex[i]);
for(i=0;i<G.vrtnum;i++) //初始化邻接矩阵,都赋为无穷
for(j=0;j<G.vrtnum;j++)
G.arcs[i][j].weight=INF;
printf("请输入%d条边的顶点1 顶点2 权值(以空格为间隔):\n",G.vrtnum);
for(int k=0;k<G.arcnum;k++){
scanf("%s%s%d%*c",va,vb,&w);
i=LocateVex(G,va);
j=LocateVex(G,vb);
G.arcs[i][j].weight=G.arcs[j][i].weight=w;
}
}
void DisplayArc(MGraph g){
printf("建立的邻接矩阵如下:\n  ");
for(int i=0;i<g.vrtnum;i++)
printf("%7s",g.vex[i]);
printf("\n");
for(int i=0;i<g.vrtnum;i++){
printf("%s",g.vex[i]);
for(int j=0;j<g.vrtnum;j++){
if(g.arcs[i][j].weight==INF)
printf("     ∞");
else
printf("%7d",g.arcs[i][j].weight);
}
printf("\n");
}
}
int findFather(int x,Father &father)
{
int root;//找x顶点的父亲
while(x!=father[x].fa)
x=father[x].fa;
root=x;//用temp存储x的最深根节点。即x的父亲结点
return root;
}
void MiniSpanTree_KRUSKAL(MGraph G){
int min=INF,i,j,vx,vy;
weightValue value,temp;
Father father;
for(i=0;i<G.vrtnum;i++)//初始化所有顶点的父亲为他自己
father[i].fa=i;
int k=0;
//将所有的边(包括边两端顶点信息),赋值到value结构体数组中
for(i=0;i<G.vrtnum;i++)
for(j=0;j<G.vrtnum;j++,k++){
value[k].w=G.arcs[i][j].weight;
value[k].x=i;value[k].y=j;
}
//对value数组中所有的边进行从大到小排序
for(i=0; i<G.vrtnum*G.vrtnum-1; i++)
for(j=0; j<G.vrtnum*G.vrtnum-1-i; j++){
if(value[j].w>value[j+1].w){
temp[0]=value[j+1];
value[j+1]=value[j];
value[j]=temp[0];
}
}
printf("克鲁斯卡尔算法的最小生成树为:\n");
int allcost=0;
for(i=0;i<2*G.arcnum-1;i+=2){
//从value数组中每隔两个点进行取边的值,因为无向图中每个顶点的值有两个
int a,b;
a=value[i].x;
b=value[i].y;
if(findFather(a,father)!=findFather(b,father)){
//当前边和其他边不构成环,就输出这条边
printf("(%s-%s) %d\n",G.vex[a],G.vex[b],G.arcs[a][b].weight);
//将此边的右顶点的父亲赋值为左顶点的父亲
father[father[b].fa].fa=findFather(a,father);
allcost+=G.arcs[a][b].weight;//每输出一次,累加此边的权值
}
}
printf("最小二叉树的最小权值为:%d\n",allcost);
}

int main(){

MGraph g;
creatMGraph(g);
DisplayArc(g);
MiniSpanTree_KRUSKAL(g);
return 0;
}
/*
测试样例:
v0 v1 v2 v3 v4 v5 v6
v0 v1 28
v1 v2 16
v2 v3 12
v3 v4 22
v4 v5 25
v5 v0 10
v1 v6 14
v3 v6 18
v4 v6 24
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息