Prim:
以某个点开始,将最近的相邻点扩充为自己新的集合,再以这个新的集合拉取新的最近点,直到所有点被拉入这个集合,这个集合就是最小生成树。
Kruskal:
“填边”的思想,将边的数据由小到大排序,若新填入的边没有形成环,则这条边就是最小生成树的一部分。判断是否形成环使用并查集的方法。
void Prim(int g[7][7]){
int included[7] = {0,1,0,0,0,0,0};//将点1设置为起点 included中在结构体的点会被标记为1
int i, j;
int sum = 0;
for (int roads = 5;roads > 0;roads--)//一共六个点 最小生成树为5条边
{
int min, mini, minj;
min = X;
for (i = 1;i < 7;i++)
{
if (included[i]) //在结构体中的点才会给予搜索
{
for (j = 1;j < 7;j++)
{
if (min > g[i][j]&&!(included[i]&&included[j]))
{
min = g[i][j];
mini = i;
minj = j;
}
}
}
}
included[minj] = 1;
sum += min;
printf("%d->%d %d\n", mini, minj, min);
}
printf("最小权值和为%d\n", sum);
}
typedef struct {
int start;
int end;
int weight;
}edge;
void edgeSwap(edge *a, edge *b){
edge *t=(edge*)malloc(sizeof(edge));
t->start = a->start;
t->end = a->end;
t->weight = a->weight;
a->start = b->start;
a->end = b->end;
a->weight = b->weight;
b->start = t->start;
b->end = t->end;
b->weight = t->weight;
free(t);
}
int find(int *pre, int x){
int r = x;
while (r != pre[r])
r = pre[r];
return r;
}
void join(int *pre, int x, int y){
int GrandX = find(pre, x);
int GrandY = find(pre, y);
pre[GrandY] = GrandX;
}
void Kruskal(int g[7][7]){
edge *a=(edge*)malloc(sizeof(edge)*100);
int x = 0;
int pre[7] = { 0,1,2,3,4,5,6 };//并查集的准备数组
for (int i = 1;i < 6;i++)//抽出边的信息
{
for (int j = i + 1;j < 7;j++)//无向图,只用对称的一边即可
{
if (g[i][j] < X)
{
a[x].start = i;
a[x].end = j;
a[x].weight = g[i][j];
x++;
}
}
}
for (int i = 0;i < x;i++)//将边由小到大排序
{
for (int j = x - 1;j > i;j--)
{
if (a[j].weight < a[j - 1].weight)
edgeSwap(&a[j], &a[j - 1]);
}
}
int sum = 0;
for (int i = 0;i < x;i++)
{
if (find(pre,a[i].start)!=find(pre,a[i].end))//判断是否在一个集合内
{
join(pre, a[i].start, a[i].end);
sum += a[i].weight;
printf("%d->%d %d\n", a[i].start, a[i].end, a[i].weight);
}
}
printf("最小权值和为%d\n", sum);
free(a);
}