求最小生成樹Kruskal算法
本文取自《數據結構與算法》(C語言版)(第三版),出版社是清華大學出版社。
在VS2010中新建C++ Win32 控制檯應用程序項目,創建結果截圖:
Kruskal算法的基本思想是:將圖G中的邊按權值從小到大的順序依次添加,如果添加的邊使生成樹T構成迴路,則將其捨棄,依此下去,直到T中包含的邊數爲n-1條邊爲止,此時的T即爲最小生樹。
Kruskal算法步驟圖示例:
爲了方便輸出,將最小生成樹的輸入格式規定爲以下形式:
(頂點1, 頂點2): 權值1
表示頂點1到頂點2有路徑,路徑上的權值爲1.
其程序如下:
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxVertexNum 100
//隊列的聲明
typedef struct Qnode
{
int data;
struct Qnode* next;
struct Qnode* prev;
}Qnode;
typedef struct queue
{
Qnode* first;
Qnode* tail;
}Queue;
int isQueueEmpty(Queue* pQue)
{
if(pQue->first==pQue->tail)
return 1;
else
return 0;
}
Queue* queueInit(Queue* pQue)
{
pQue->first=(Qnode*)malloc(sizeof(Queue));
pQue->first->data=-1;
pQue->tail=pQue->first;
return pQue;
}
Qnode* queuePull(Queue* pQue)
{
pQue->tail=pQue->tail->prev;
return pQue->tail->next;
}
void queuePush(Queue* pQue, Qnode* pNode)
{
pNode->next=pQue->first;
pQue->first->prev=pNode;
pQue->first=pNode;
}
Queue* queueEmpty(Queue* pQue)
{
while(pQue->first!=pQue->tail)
{
Qnode* pCurr=pQue->first;
pQue->first=pQue->first->next;
free(pQue->first);
}
return pQue;
}
//圖的聲明
typedef struct node
{
int adjvex;
int hostvex;
struct node *nextrarc;
int info;
}EdgeNode;
typedef struct vnode
{
char vexdate;
EdgeNode *firstarc;
}VertexNode;
typedef VertexNode AdjList[MaxVertexNum];
typedef struct
{
AdjList adjlist;
int n,e;
}ALGraph;
int initGraph(ALGraph* aGraph);
int mFind(char aChar, ALGraph* aGraph);
int createHead(char aChar, ALGraph* aGraph);
void addBody(char aChar, int aPos, ALGraph* aGraph, int weight);
void Kruskal(ALGraph* aGraph);
int main(void)
{
char a;
int isFinish=0;
int headPos=-1;
char a1='@', a2='@', a3='@', a4='@', a5='@', a6='@', a7='@';
ALGraph g_graph;
initGraph(&g_graph);
printf("Input arcs like this '(start,end:weight)',end with $\n");
while(isFinish==0)
{
while(1)
{
a=getchar();
if(a=='$'||a=='#')
{
if(a=='#')
isFinish=1;
break;
}
if(a==' '||a=='\n')
continue;
a1=a2;
a2=a3;
a3=a4;
a4=a5;
a5=a6;
a6=a7;
a7=a;
if(a1=='('&&a3==','&&a5==':'&&a7==')')
{
if((headPos=mFind(a2,&g_graph))==-1)
headPos=createHead(a2,&g_graph);
addBody(a4,headPos,&g_graph,a6);
}
}
}
Kruskal(&g_graph);
return 0;
}
void Kruskal(ALGraph* aGraph)
{
int i,j,u1,v1,sn1,sn2,k;
int vset[MaxVertexNum];
EdgeNode* E[MaxVertexNum];
k=0;
for(i=0; i<aGraph->n; i++)
{
EdgeNode* temEdge;
for(temEdge=aGraph->adjlist[i].firstarc; temEdge!=NULL;
temEdge=temEdge->nextrarc)
{
E[k]=temEdge;
k++;
}
}
//將邊的權值進行排序
for(i=0; i<aGraph->e; i++)
{
for(j=aGraph->e-1; j>i; j--)
if(E[j]->info<E[j-1]->info)
{
EdgeNode* tem=E[j];
E[j]=E[j-1];
E[j-1]=tem;
}
}
for(i=0; i<aGraph->n; i++)
vset[i]=i;
k=1;
j=0;
//添加邊
while(k<aGraph->n)
{
u1=E[j]->hostvex;
v1=E[j]->adjvex;
sn1=vset[u1];
sn2=vset[v1];
if(sn1!=sn2)
{
printf("(%d,%d):%c\n",u1,v1,E[j]->info);
k++;
for(i=0; i<aGraph->n; i++)
if(vset[i]==sn2)
vset[i]=sn1;
}
j+=2;
}
}
void addBody(char aChar, int aPos, ALGraph* aGraph, int weight)
{
int inversePos;
EdgeNode* node=(EdgeNode*) malloc(sizeof(EdgeNode));
node->info=weight;
if((node->adjvex=mFind(aChar,aGraph))==-1)
node->adjvex=createHead(aChar,aGraph);
node->hostvex=aPos;
node->nextrarc=NULL;
if(aGraph->adjlist[aPos].firstarc==NULL)
aGraph->adjlist[aPos].firstarc=node;
else
{
EdgeNode* tail=aGraph->adjlist[aPos].firstarc;
while(tail->nextrarc!=NULL)
tail=tail->nextrarc;
tail->nextrarc=node;
}
aGraph->e++;
inversePos=node->adjvex;
node=(EdgeNode*) malloc(sizeof(EdgeNode));
node->info=weight;
node->hostvex=inversePos;
node->adjvex=aPos;
node->nextrarc=NULL;
if(aGraph->adjlist[inversePos].firstarc==NULL)
aGraph->adjlist[inversePos].firstarc=node;
else
{
EdgeNode* tail=aGraph->adjlist[inversePos].firstarc;
while(tail->nextrarc!=NULL)
tail=tail->nextrarc;
tail->nextrarc=node;
}
aGraph->e++;
}
int createHead(char aChar, ALGraph* aGraph)
{
int currPos=aGraph->n;
aGraph->adjlist[currPos].vexdate=aChar;
aGraph->n++;
return currPos;
}
int mFind(char aChar, ALGraph* aGraph)
{
int i=0;
for(i=0; i<aGraph->n; i++)
{
if(aChar==aGraph->adjlist[i].vexdate)
return i;
}
return -1;
}
int initGraph(ALGraph* aGraph)
{
int i=0;
aGraph->e=0;
aGraph->n=0;
for(i=0; i<MaxVertexNum; i++)
{
aGraph->adjlist[i].firstarc=NULL;
}
return 0;
}
程序運行結果截圖如下:Ctrl+F5執行程序Kruskal.cpp