自己根据kruakal的算法(核心是贪心算法)描述写了一个最小生成树的代码,
- #include <stdio.h>
-
#include <stdlib.h>
-
#include <strings.h>
-
-
#define INT32 int
-
#define MAXNUMEDGE 1024
-
#define PRINTF
-
-
typedef struct EDGE_H
-
{
-
INT32 u;
-
INT32 v;
-
INT32 key;
-
}EDGE;
-
-
//边从0开始计数
-
EDGE edge[MAXNUMEDGE]; //用来存储所有的边的数据
-
static INT32 numberofedge;
-
EDGE *minspanedge; //生成树时用到的边
-
INT32 *minspancity; //使用的边所属于的集合
-
-
//交换边
-
int swapedge(INT32 iedge, INT32 jedge)
-
{
-
if(iedge>= numberofedge||jedge>=numberofedge)
-
return 0;
-
-
EDGE tmp;
-
tmp.u = edge[iedge].u;
-
tmp.v = edge[iedge].v;
-
tmp.key = edge[iedge].key;
-
-
edge[iedge].u = edge[jedge].u;
-
edge[iedge].v = edge[jedge].v;
-
edge[iedge].key = edge[jedge].key;
-
-
edge[jedge].u = tmp.u;
-
edge[jedge].v = tmp.v;
-
edge[jedge].key = tmp.key;
-
-
return 1;
-
-
}
-
-
/*
-
* 得到两个边的较小边
-
* */
-
INT32 minedge(const int iedge,const int jedge)
-
{
-
int minnumedge;
-
minnumedge = edge[iedge].key>edge[jedge].key?jedge:iedge;
-
return minnumedge;
-
}
-
-
/*
-
* 通过最小堆的方式来每次得到最小边
-
* */
-
void minheapofedge(INT32 count)
-
{
-
int i;
-
INT32 minkeynum;
-
for(i=((numberofedge-count)>>1)-1; i>=0; i--)
-
{
-
if(((i>>1)+2)<(numberofedge-count))//右结点存在
-
{
-
minkeynum = minedge((i>>1)+2,(i>>1)+1);
-
-
if(edge[i].key>edge[minkeynum].key)//做交换
-
{
-
swapedge(i,minkeynum);
-
}
-
}
-
else//右节点不存在
-
{
-
if(edge[i].key>edge[(i>>1)+1].key)
-
{
-
swapedge(i,(i>>1)+1);
-
}
-
}
-
}
-
}
-
-
/*
-
* 查找元素是否属于集合,返回集合的头
-
* */
-
INT32 isset(const INT32 ucity)
-
{
-
INT32 tempcity=ucity;
-
if(ucity == minspancity[ucity]){}
-
else
-
{
-
while(tempcity != minspancity[tempcity])
-
{
-
tempcity = minspancity[tempcity];
-
}
-
}
-
printf("isset:ucity:%d,set:%d\n",ucity,tempcity);
-
return tempcity;
-
}
-
-
/*
-
* 合并两个集合
-
* */
-
void mergeset(INT32 uset,INT32 vset)
-
{
-
if(minspancity[uset]>minspancity[vset])
-
minspancity[uset]=minspancity[vset];
-
else
-
minspancity[vset]=minspancity[uset];
-
}
-
/*
-
* 最小生成树
-
* */
-
void minspantree()
-
{
-
-
INT32 i,count=0;
-
INT32 ucity,vcity;
-
EDGE minedge;
-
for(i=0; i<numberofedge; i++)
-
{
-
minheapofedge(count);
-
minedge = edge[0];//得到了最小边 //------------------------------------------(1)
-
#ifdef PRINTF
-
printf("minedge:u%d,v%d,key%d\n",minedge.u,minedge.v,minedge.key);
-
#endif
-
ucity = isset(minedge.u);
-
vcity = isset(minedge.v);
-
if(ucity!=vcity)
-
{
-
//把两个集合合并
-
mergeset(ucity,vcity);
-
-
//把边添加进最小生成树里面
-
minspanedge[count] = minedge;
-
count++;
-
-
}
-
else
-
{
-
/*
-
if(minspancity[ucity]>minspancity[vcity])
-
minspancity[vcity] = minspancity[ucity];
-
else
-
minspancity[ucity] = minspancity[vcity];
-
*/
-
}
-
-
//把选出的边处理了
-
swapedge(0,numberofedge-i-1);
-
-
}
-
}
-
-
-
/*
-
* 读取道路的数据
-
* */
-
int readroad()
-
{
-
int ucity,vcity,distance;
-
int i;
-
for(i=0; i<numberofedge; i++)
-
{
-
scanf("%d %d %d",&ucity,&vcity,&distance);
-
edge[i].u = ucity;
-
edge[i].v = vcity;
-
edge[i].key = distance;
-
}
-
return i;
-
-
}
-
-
-
int main()
-
{
-
printf("请输入城市个数和城市之间的道路条数\n");
-
printf("请输入具体的两个城市和道路名\n");
-
-
int numofcities,cities,i;
-
scanf("%d %d",&numofcities,&cities);
-
numberofedge = cities;
-
minspanedge = (EDGE *)malloc(sizeof(EDGE)*numberofedge);
-
bzero(minspanedge,sizeof(minspanedge));
-
minspancity = (INT32 *)malloc(sizeof(INT32)*numofcities);
-
-
for(i=0; i<numofcities; i++)
-
minspancity[i] = i;
-
-
if(numberofedge != readroad()||numberofedge<numofcities-1)
-
{
-
printf("readroad read error!\n");
-
return ;
-
}
-
/*
-
swapedge(0,1);
-
for(i=0; i<numberofedge; i++)
-
{
-
printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].key);
-
}
-
*/
-
minspantree();
-
-
printf("城市 城市 距离\n");
-
for(i=0; i<numofcities-1; i++)
-
printf("%d %d %d\n",minspanedge[i].u,minspanedge[i].v,minspanedge[i].key);
-
-
-
-
}
在这次写的代码中发现思路上都是正确的,每个函数的代码都是正确的,但是在变量的使用上太不小心了,就是因为变量的错误导致运行的结果出现错误。
结构体是可以直接赋值的,如(1)处。
阅读(1404) | 评论(0) | 转发(0) |