您的位置:首页 > 其它

第七章-图(5)图的最小生成树(Kruskal和Prim算法)

2018-03-15 21:49 513 查看




--------------------------------------------------------------------------------------------------------------------------------
代码:(C语言实现)#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#define ERROR 0
#define OK 1
#define INFINITY INT_MAX //最大值
#define MAX_VERTEX_NUM 21 //最大顶点个数
#define MAX 20

typedef enum{ DG,DN,UDG,UDN } GraphKind; //{有向图,有向网,无向图,无向网}

//--------图的数组(邻接矩阵)存储表示------//
typedef struct ArcCell{
int adj; // int 可用 VRType代替 ,VRType是顶点关系类型。对无权图,用1或者0
// 表示相邻否; 对带权图,则为权值类型
// InforType *info; //该弧相关信息指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct{
char vexs[MAX_VERTEX_NUM]; //顶点向量 书中用 VertexType 代替 char
AdjMatrix arcs; //邻接矩阵
int vexnum,arcnum; //图的当前顶点数和弧数
GraphKind kind; //图的种类标志
}MGraph;
//----------------------------------------//

typedef struct{
char adjvex;
int lowcost;
}closedges[MAX_VERTEX_NUM]; //求最小生成树中的辅助数组

typedef struct EdgeData
{
char start; //起始点
char end; //终点
int weight; //权重
}EGraph;

//邻接矩阵顶点定位
int LocateVex(MGraph G,char v){
int m;
for(m=1;m<=G.vexnum;m++)
if(G.vexs[m]==v)
return m;
return ERROR;
return OK;
}

//创建无向网邻接矩阵
int CreatGraph(MGraph &G){
int i,j,k,w;
char x,y;

printf("请输入邻接矩阵: 顶点的个数 、弧的个数:");
scanf("%d %d",&G.vexnum,&G.arcnum); //构造顶点向量
if(G.vexnum>20){ //顶点个数过多
printf("你输入的顶点个数超过最大值");
return ERROR;
}
printf("请输入 %d 个顶点的值",G.vexnum);

for(i=1;i<=G.vexnum;i++){
fflush(stdin);
scanf("%c",&G.vexs[i]); //构造顶点向量的值
}

for(i=1;i<=G.vexnum;i++)
for(j=1;j<=G.vexnum;j++)
G.arcs[i][j].adj=INT_MAX; //初始化

printf("请输入无向网的两个相邻的顶点 (x,y) 以及相应的权值 w :\n");;
for(k=1;k<=G.arcnum;k++){
fflush(stdin);
scanf("%c %c %d",&x,&y,&w);
i=LocateVex(G,x);
j=LocateVex(G,y);
G.arcs[i][j].adj=w;
G.arcs[j][i].adj=G.arcs[i][j].adj;
}
return OK;
}

//输出邻接表
int OutGraph(MGraph G1){
int i,j;
printf("无向网的邻接矩阵: \n");
for(i=1;i<=G1.vexnum;i++){ //将邻接矩阵输出
for(j=1;j<=G1.vexnum;j++){
if(G1.arcs[i][j].adj==INT_MAX)
printf("#");
else
printf("%d",G1.arcs[i][j].adj);
}
printf("\n");
}
return OK;
}

int Minimun(MGraph G,closedges m){
int i,j,min=INFINITY;
for(i=1;i<=G.vexnum;i++){
if(m[i].lowcost){
if(m[i].lowcost<min){
min=m[i].lowcost;
j=i;
}
}
}
return j;
}

//对权重进行排序
int sort_edge(EGraph G1[],MGraph G){
int i,j;
int dex=1;
for(i=1;i<=G.arcnum;i++){
for
4000
(j=i;j<=G.arcnum;j++){
if(G.arcs[i][j].adj!=INT_MAX){
G1[dex].start=G.vexs[i];
G1[dex].end=G.vexs[j];
G1[dex].weight=G.arcs[i][j].adj;
// printf("%c %c %d \n",G1[dex].start,G1[dex].end,G1[dex].weight);
dex++;
}
}
}
for(i=1;i<=G.vexnum;i++){
for(j=i+1;j<=G.vexnum;j++){
if(G1[i].weight > G1[j].weight){
EGraph tmp=G1[i];
G1[i]=G1[j];
G1[j]=tmp;
}
}
}
for(i=1;i<=G.arcnum;i++){
printf("%c %c %d \n",G1[i].start,G1[i].end,G1[i].weight);
}
return OK;
}

static int get_position(MGraph G,char ch){
int i;
for(i=1;i<=G.vexnum;i++)
if(G.vexs[i]==ch)
return i;
return -1;
} //得到字符在数组中的位置

int get_end(int vends[],int i){
while(vends[i]!=0)
i=vends[i];
return i;
}

//使用克鲁斯卡尔算法
int kruskal(MGraph G){
int i;
int p1,p2,m,n;
int index=0;
EGraph G1[MAX];
EGraph rets[MAX];
int vends[MAX]={0};
sort_edge(G1,G); //进行排序
for(i=1;i<=G.arcnum;i++){
p1=get_position(G,G1[i].start);
p2=get_position(G,G1[i].end);
m=get_end(vends,p1);
n=get_end(vends,p2);
printf("m= %d,n= %d \n",m,n);
if(m!=n){
vends[m]=n;
rets[index]=G1[i];
index++;
}
}

int length=0;

for(i=0;i<index;i++){
printf("%d ",rets[i].weight);
length=length+rets[i].weight;
}
printf("Kruskal = %d \n",length);
for(i=0;i<index;i++)
printf("%c-%c ",rets[i].start,rets[i].end);
printf("\n");
return OK;
}

//用普里姆算法从第 u 个顶点出发构造网 G 的最小生成树 T ,输出T的各条边
//记录从顶点集 U 到 V-U 的代价最小的边的辅助数组定义
int CreatMinTree(MGraph G){
char u;
int i,j,k;
closedges closedge;

printf("请输入第一个顶点:");
fflush(stdin);
scanf("%c",&u);
printf("无向网的最小生成树:\n");

k=LocateVex(G,u);
for(j=1;j<=G.vexnum;j++){ //辅助数组初始化
if(j!=k){
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
closedge[k].lowcost=0;
for(i=2;i<=G.vexnum;i++){
k=Minimun(G,closedge);
printf("%c-%c ",closedge[k].adjvex,G.vexs[k]);
closedge[k].lowcost=0;
for(j=1;j<=G.vexnum;j++)
if(G.arcs[k][j].adj<closedge[j].lowcost){ //新顶点并入 U 后重新选择最小边
closedge[j].adjvex=G.vexs[k];
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
return OK;
}

void main(){
MGraph G;
CreatGraph(G);
OutGraph(G);
CreatMinTree(G);
printf("\n");
kruskal(G);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: