对于城市交通问题,有一个要解决的问题是如何使n个城市之间在最节省经费的情况下建立交通路线,保证连通n个城市,在所有的线路中选择代价最小的。最小生成树就可以解决这一问题。
要构成最小生成树,必须满足一下两个条件
(1)尽可能选取权值最小的,但是不能构成回路。
(2)选取n-1条恰当的边连接往中的n个顶点。
Kruskal算法的基本思想:对于一个n个顶点的图,从权值最小的边开始,若它的添加不会与集合中已添加的边构成回路,则将该边添加到集合中。依次按照权值递增的顺序,选择合适的边进行添加,如此重复,直到加完n-1条边为止。
<pre name="code" class="cpp">#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){ <pre name="code" class="java">int n,num = 0; int x=0,y=0; int count = 0;<pre name="code" class="java"><span style="white-space:pre"> </span>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){
<span style="white-space:pre"> </span>temp = graph[colCount].countfor(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;
<pre name="code" class="java"> } } 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); }