最小生成树( 克鲁斯卡尔算法)
/*
Name:
Copyright:
Author:
Date: 01-12-14 20:17
Description: 最小生成树( 克鲁斯卡尔算法)
关于并查集的算法,参见《一种简单而有趣的数据结构——并查集》http://blog.csdn.net/qiaoruozhuo/article/details/39674991
*/
#include#include#define MAXN 1000 //最大顶点数量
#define MAX 20000 //最大边数量
#define INFINITY 999999 //无穷大
int map[MAX][MAX] = {0};//邻接矩阵存储图信息
typedef struct EdgeNode{ //三元组边表集
int u, v; //弧尾和弧头
int w; //权值,对于非网图可以不需要
} EdgeNode;
void CreatGraph(EdgeNode *E, int m);//创建三元组边表集图
void CreatGraph_2(EdgeNode *E, int m, int n);//创建邻接矩阵图(随机图)
int Locate(EdgeNode *E, int n, int u, int v);//判断u,v是否是邻接点
void PrintGraph(EdgeNode *E, int m);//输出图
int cmp (const void *a , const void *b);//快排的配套函数
int FindFatherAndReducePath(int father[], int pos);//查找族长并压缩路径:找到族长后,将所途经的前辈结点均指向族长
int UnionBySize(int father[], int posI, int posJ);//按大小求并:将成员posI和posJ合并到同一个家族
void KRSL(EdgeNode *E, int m, int n);//克鲁斯卡尔算法求最小生成树
int main()
{
EdgeNode E[MAX];
int i, m, n;
printf("请输入顶点数量:");
scanf("%d", &n);
printf("\n请输入边数量:");
scanf("%d", &m);
CreatGraph_2(E, m, n);//创建三元组边表集图
PrintGraph(E, m);//输出图
qsort(E, m, sizeof(E[0]), cmp);//按照权值大小递增排序
PrintGraph(E, m);//输出图
KRSL(E, m, n);//克鲁斯卡尔算法求最小生成树
return 0;
}
void CreatGraph(EdgeNode *E, int m)//创建三元组边表集图
{
int i;
printf("\n请按照a b c格式输入边信息:\n");
for (i=0; i= %d\t", E[i].u, E[i].v, E[i].w);
}
printf("\n");
}
int cmp (const void *a , const void *b)//快排的配套函数
{
return (((EdgeNode *)a)->w > ((EdgeNode *)b)->w ? 1 : -1);
}
void KRSL(EdgeNode *E, int m, int n)//克鲁斯卡尔算法求最小生成树
{
int i, min, top = 1;
int father[MAXN] = {0};
EdgeNode minTree[MAXN] = {0};
for (i=0; i= %d\t", minTree[i].u, minTree[i].v, minTree[i].w);
min += minTree[i].w;
}
printf("\n最小生成树总长度(权值)为 %d\n", min);
}
int FindFatherAndReducePath(int father[], int pos)//查找族长并压缩路径:找到族长后,将所途经的前辈结点均指向族长
{
if (father[pos] <= 0)
return pos;
//若自己不是族长,则找到族长后,将所途经的结点均指向族长
return father[pos] = FindFatherAndReducePath(father, father[pos]);
}
int UnionBySize(int father[], int posI, int posJ)//按大小求并:将成员posI和posJ合并到同一个家族
{
//首先各自去寻找自己的族长
int fI = FindFatherAndReducePath(father, posI);
int fJ = FindFatherAndReducePath(father, posJ);
if (fI == fJ) //如果是同一个族长门下,不必合并,即合并失败
return 0;
if (father[fI] < father[fJ])
{//如果族长fI的实力比fJ强,即|fI|>|fJ|,则fI当族长,并修改father[fI]和father[fJ]
father[fI] += father[fJ];
father[fJ] = fI;
}
else //否则fJ当族长
{
father[fJ] += father[fI];
father[fI] = fJ;
}
return 1;
}
http://www.dengb.com/Javabc/921128.htmlwww.dengb.comtruehttp://www.dengb.com/Javabc/921128.htmlTechArticle最小生成树( 克鲁斯卡尔算法) /*Name: Copyright: Author: Date: 01-12-14 20:17Description: 最小生成树( 克鲁斯卡尔算法)关于并查集的算法,参见《...