typedef struct ANode{
int adjvex;
struct ANode * nextarc;
int info;
}ArcNode;
//边节点类型
typedef struct Vnode{
char data;
ArcNode *firstarc;
}VNode,AdjList[MAXV];
//表头结点信息
typedef struct {
AdjList adjlist;
int n,e; //顶点数,边数
}ALGraph;
//完整的图邻接表类型
最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树
生成过程:
-创建连通网G
void CreateALGraph(ALGraph *G){
int i,j,k,w;
ArcNode *p;
printf("请输入顶点数和边数\n");
scanf("%d,%d",&G->n,&G->e);
for (i=0; i < G->n;i++) {
printf("请输入顶点信息\n");
scanf("%s",&G->adjlist[i].data);
G->adjlist[i].firstarc=NULL;
}
for (k=0; k<G->e; k++) {
printf("输入第%d条边的两顶点编号和权值:",k+1);
scanf("%d,%d,%d",&i,&j,&w); //顶点编号0,顶点编号1,两者的权值
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=j;
p->info = w;
p->nextarc=G->adjlist[i].firstarc;
G->adjlist[i].firstarc=p;
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=i;
p->info =NULL;
p->nextarc=G->adjlist[j].firstarc;
G->adjlist[j].firstarc=p;
}
}
-最小生成树E
void CreateKruskal(ALGraph *G,ALGraph *E){
int i ,j=0;
int bj[MAXV];
int a[MAXV],b[MAXV]; //a里面放权值,b里放相应权值对应的顶点行(减少遍历次数,提高效率)
int min,min_dex,ls;//连锁标记
int result=0;
E->n=G->n;
E->e=G->e;
ArcNode *p;
ArcNode *q;
for (i=0; in; i++) { //循环顶点 a,b,c,d,e,f
for (p=G->adjlist[i].firstarc; p!=NULL; p=p->nextarc){
if (p->info!=NULL) {
a[j]=p->info;
b[j]=i;
j++;
}
}
} //a,b 创建好,j中是权值个数
for (i=0; in; i++) {
bj[i]=i;
}//建立bj[]标记表(不同标记,代表不同的树)
while(result==0){
min=a[0];
min_dex=0;
for (i=1; iif (a[i]< min) {
min=a[i];
min_dex=i;
}
}
a[min_dex]=a[j-1]+1; //去掉最小值(把当前拿出的最小值变成 最大值+1)
for (p=G->adjlist[b[min_dex]].firstarc; p!=NULL; p=p->nextarc){
if (p->info==min) {
if (bj[b[min_dex]] != bj[p->adjvex]) {
ls=bj[p->adjvex];
for (i=0; in; i++) { //这个循环解决当标记表为{0,0,1,1}时,连接一个0和1,自动把剩下的1变为0,【达到连接两个树的目的】
if (bj[i]==ls) {
bj[i]=bj[b[min_dex]];
}
}
q=(ArcNode *)malloc(sizeof(ArcNode));
q->adjvex=p->adjvex;
q->info=p->info;
q->nextarc=E->adjlist[b[min_dex]].firstarc;
E->adjlist[b[min_dex]].firstarc = q;
}
}//在a中找最小值,通过下标,在b中找哪一行顶点,判断p->info是否与最小值相等,相等就把adjvex 顶点信息 判断加入到E中
result=1;
for(i = 0; in; i++){
if(a[0] != a[i])
{
result=0;
break;
}
}// 如果标记数组全部相等(成一颗树) 则循环结束
}
}
a[]={1,2,3,4,5,5,5,6,6,6}
bj[]={ 0, 1, 2, 3, 4, 5 } 相当于5颗树
对应 =A·B··C··D··E···F
第一次循环从a中拿出权值1,并在顶点A,C中找到,加入E后,bj[]={0,1,0,3,4,5}
第二次循环从a中拿出权值2,并在顶点D,F中找到,加入E后,bj[]={0,1,0,3,4,3}
第三次循环从a中拿出权值3,并在顶点B,E中找到,加入E后,bj[]={0,1,0,3,1,3}
第四次循环从a中拿出权值4,并在顶点C,F中找到,加入E后,bj[]={0,1,0,0,1,0}
第五次循环从a中拿出权值5,当在顶点A,D中找到时,因为A,D的标记均为0,表示在一颗树上,所以不放入E
第六次循环从a中拿出权值5,当在顶点B,C中找到时,因为B,C标记为1,0 不在同一颗树上,所以放入E,此时bj[]={0,0,0,0,0}
循环结束,打印结果
打印代码与main函数如下
void DispALGraph(ALGraph *G){
int i,max=0,max_index=0;
ArcNode *p;
printf("图的邻接表如下:\n");
printf("编号 顶点 相邻编号,权值\n");
for (i=0; in; i++) {
int j=0;
printf("%4d %8c",i,G->adjlist[i].data);
for (p=G->adjlist[i].firstarc; p!=NULL; p=p->nextarc) {
printf(" --> ");
printf("%d,%d",p->adjvex,p->info);
j++;
if (maxprintf("\t该顶点有%d个边\n",j);
}
printf(" 编号%d有最多度\n",max_index);
}
int main(){
ALGraph G; //无向网连通网G
ALGraph E; //最小生成树
CreateALGraph(&G); //在每个头结点后面加上边的信息
DispALGraph(&G); //打印无向网
CreateKruskal(&G,&E);//创建最小生成树
DispALGraph(&E);//打印最小生成树
return 0;
}
其中两个生成树图来自
http://blog.csdn.net/luoshixian099/article/details/51908175