对于城市交通问题,有一个要解决的问题是如何使n个城市之间在最节省经费的情况下建立交通路线,保证连通n个城市,在所有的线路中选择代价最小的。最小生成树就可以解决这一问题。
要构成最小生成树,必须满足一下两个条件
(1)尽可能选取权值最小的,但是不能构成回路。
(2)选取n-1条恰当的边连接往中的n个顶点。
Kruskal算法的基本思想:对于一个n个顶点的图,从权值最小的边开始,若它的添加不会与集合中已添加的边构成回路,则将该边添加到集合中。依次按照权值递增的顺序,选择合适的边进行添加,如此重复,直到加完n-1条边为止。
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define N 10
struct Graph {
char row[N];
char col[N];
int weight;
struct Graph *next;
};
struct temp{
char vexnum[N];
int weight;
};
int k=0;
/*
*创建链表存储图的顶点和权值
*/
struct Graph *create(int n){
srand((unsigned)time(NULL));
struct Graph *pHead=NULL;
struct Graph *pEnd,*pNew;
struct Graph *t;
pEnd = pNew = (struct Graph *)malloc(sizeof(struct Graph));
printf("Please input a pair of vexnums and a weight(stop when input '0'):\n");
printf("vexnum1\tvexnum2\tweight\n");
scanf("%s",&pNew->row);
scanf("%s",&pNew->col);
scanf("%d",&pNew->weight);
while(1){
k++;
if(k == 1){
pNew->next = pHead;
pEnd = pNew;
t = pHead = pNew;
}
else{
pNew->next = NULL;
pEnd->next = pNew;
pEnd = pNew;
}
if(k == n*(n-1)/2){
break;
}
pNew=(struct Graph *)malloc(sizeof(struct Graph));
scanf("%s",&pNew->row);
if(strcmp(pNew->row,"0") == 0){
break;
}
scanf("%s",&pNew->col);
scanf("%d",&pNew->weight);
}
return pHead;
}
/*
*对输入的顶点进行判断,删掉重复的边
*/
Arrange(struct Graph *p){
struct Graph *q,*s;
s = p;
q = p->next;
while(1){
while(q != NULL){
if(strcmp(p->row,q->row) == 0 && strcmp(p->col,q->col) == 0
|| strcmp(p->row,q->col) == 0 && strcmp(p->col,q->row) == 0){
p->next = q->next;
free(q);
q = p->next;
continue;
}
if(q == NULL)
break;
else
q = q->next;
}
s = s->next;
if(s == NULL)
break;
p = s;
q = p->next;
}
}
/*
*对每条边的权值按照从小到大的顺序排序
*/
sort(struct Graph *New){
char row[N],col[N];
int weight;
struct Graph *End;
while(New->next!=NULL){
End = New->next;
while(End!=NULL){
if(New->weight>End->weight){
strcpy(row,New->row);
strcpy(New->row,End->row);
strcpy(End->row,row);
strcpy(col,New->col);
strcpy(New->col,End->col);
strcpy(End->col,col);
weight = New->weight;
New->weight = End->weight;
End->weight = weight;
}
End = End->next;
}
New = New->next;
}
}
print(struct Graph *p){
printf("创建的图为\n");
while(p != NULL){
printf("%s---%s\t",p->row,p->col);
printf("%d\n",p->weight);
p = p->next;
}
}
/*
*从最小的权值对应的边开始,若它的添加不会与集合中已添加的边构成回路,则将该边添加到集合中。
*/
found(struct Graph *p,int j){
int n,num = 0;
int x=0,y=0;
int count = 0;
int temp = 0;
int rowCount = 0,colCount = 0;
struct temp graph[k];
printf("最小生成树的边为:\n");
while(p != NULL){
if(num == 0){
printf("%s---%s\n",p->row,p->col);
strcpy(graph[num].vexnum,p->row);
strcpy(graph[num+1].vexnum,p->col);
graph[num].count = graph[num+1].count = count;
count ++;
num += 2;
p = p->next;
continue;
}
for(n = 0;n < num;n ++){
if(strcmp(p->row,graph[n].vexnum) == 0){
rowCount = n;
x=1;
break;
}
}
for(n = 0;n < num;n ++){
if(strcmp(p->col,graph[n].vexnum) == 0){
colCount = n;
y=1;
break;
}
}
if(x == 0 && y == 0){
strcpy(graph[num].vexnum,p->row);
strcpy(graph[num+1].vexnum,p->col);
graph[num].count = graph[num+1].count = count;
num += 2;
count ++;
printf("%s---%s\n",p->row,p->col);
p = p->next;
} else if(x == 1 && y == 0){
strcpy(graph[num].vexnum,p->col);
graph[num].count = graph[rowCount].count;
num++;
printf("%s---%s\n",p->row,p->col);
p = p->next;
} else if(x == 0 && y == 1){
strcpy(graph[num].vexnum,p->row);
graph[num].count = graph[colCount].count;
num++;printf("%s---%s\n",p->row,p->col);
p = p->next;
} else if(x == 1 && y == 1 && graph[rowCount].count != graph[colCount].count){
temp = graph[colCount].count
for(n = 0 ; n < num ; n++){
if(graph[n].count == temp){
graph[n].count = graph[rowCount].count;
}
}
printf("%s---%s\n",p->row,p->col);
p = p->next;
} else {
x = y = 0;
p = p->next;
continue;
}
x = y = 0;
}
}
main(){
struct Graph *Head;
int i;
printf("Please input the number of the vexnum\n");
scanf("%d",&i);
while(i == 1 || i == 0){
printf("Error, please input again\n");
scanf("%d",&i);
}
Head = create(i);
Arrange(Head);
sort(Head);
print(Head);
found(Head,i);
}