2. Kruskal
将边按权值从小到大排列【取出之后不再需要处理,所以可以考虑用最小堆进行排序】
然后 按照权值递增的顺序查看每一条边:
假如第k条边(v, w), 如果两个端点 v 和 w 分别在当前两个不同的连通分支中, 就用变 边(v, w)将 两个连通分支连接起来
否则 直接处理下一条边
++++++++++++++++++++++++++++
PS:
1. 这个需要用到 小根堆。 关于小根堆,只是堆排序中的一个步骤。它只保证最顶端的是最小的元素。当取走这个元素之后,重新进行一次堆调整,然后,堆顶元素又是最小的了。
2. 建小根堆的时候要特别注意,
int start = heapsize / 2 - 1;
for (; start >= 0; start--)
small_root_heapify(heap, start, heapsize );
个数,起始点编号和是否取到编号0这个问题
3. 关于Kruskal里面,判断两个端点v和w是否在不同的连通分支中。
所以这个需要给每个端点打标记。最开始用的 o or 1,认为加入和不加入两种情况,可是这样,所有的点开始都是0, v != w时才可以加入,所以没有可加入点了==
后来,给每个点打标记为自身编号,每个加入的边,后一个点的标记 记为 前一个点的标记。同时,需要判断加入的边的条数k, 用来防止生成了闭环。
++++++++++++++++++++++++++++
/ alg_for_test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <float.h> //FLT_MAX
#include <stdlib.h>
#define NUMOFDOT 6 //点的个数
//定义一条边,两个点及其边的权值
typedef struct node
{
int node1;
int node2;
float weight;
}EdgeNode;
void createMinHeap(EdgeNode *heap, int heapSize) ;
EdgeNode removeMin(EdgeNode *heap, int heapSize) ;
void small_root_heapify(EdgeNode *heap, int i, int heapSize) ;
void printHeap(EdgeNode heap[],int HeapSize);
void kruskal(EdgeNode myEdgeNode[] );
int main()
{
float c[NUMOFDOT][NUMOFDOT] = {
FLT_MAX, 6, 1, 5, FLT_MAX, FLT_MAX,
6, FLT_MAX, 5, FLT_MAX, 3, FLT_MAX,
1, 5, FLT_MAX, 5, 6, 4,
5, FLT_MAX, 5, FLT_MAX, FLT_MAX, 2,
FLT_MAX, 3, 6, FLT_MAX, FLT_MAX, 6,
FLT_MAX, FLT_MAX, 4, 2, 6, FLT_MAX
};
EdgeNode myEdgeNode[NUMOFDOT * NUMOFDOT];
int cnt = 0;
for(int i = 0; i < NUMOFDOT; i++)
{
for(int j = 0; j < NUMOFDOT; j++)
{
myEdgeNode[cnt].node1 = i;
myEdgeNode[cnt].node2 = j;
myEdgeNode[cnt].weight = c[i][j];
cnt++;
}
}
kruskal(myEdgeNode);
system("pause");
return 0;
}
void kruskal(EdgeNode myEdgeNode[] )
{
int e = NUMOFDOT * NUMOFDOT;
int flag[NUMOFDOT] = {0, 1, 2, 3, 4, 5 };// 打标机,0表示未加入 "团"
//printHeap(myEdgeNode, e);
createMinHeap(myEdgeNode, e);
//printHeap(myEdgeNode, e);
int k = 0; //用来记录已经加入的点的个数
while(e > 0 && k < NUMOFDOT - 1)
{
EdgeNode x = (EdgeNode) removeMin(myEdgeNode, e); //从堆中去出权值最小的一条边
//for test
//printf("e = %d\t, %d, %d, %f \n", e, x.node1, x.node2, x.weight);
int a = flag[x.node1];
int b = flag[x.node2];
//如果取出的这一条边的两个端点不在一个联通域中,这条边可连接起来
if(a != b )
{
printf("edges %d --- %d added\n", x.node1, x.node2);
//将这两点连接起来,ab属于一个连通域了。。
flag[x.node2] = flag[x.node1];
k++;
}
e--; //边数-1
}
}
void printHeap(EdgeNode heap[],int HeapSize)
{
for(int i = 0;i < HeapSize; ++i)
{
printf("heap's node1 = %d, node2 = %d, weight = %f\n", heap[i].node1, heap[i].node2, heap[i].weight);
}
}
void createMinHeap(EdgeNode *heap, int heapsize)
{
int start = heapsize / 2 - 1;
for (; start >= 0; start--)
small_root_heapify(heap, start, heapsize );
}
void small_root_heapify(EdgeNode *heap, int i, int heapsize)
{
int l = 2 * i + 1;
int r = 2 * i + 2;
int smallest;
EdgeNode temp;
if (l < heapsize && heap[l].weight < heap[i].weight)
smallest = l;
else
smallest = i;
if (r < heapsize && heap[r].weight < heap[smallest].weight)
smallest = r;
if (i != smallest)
{
temp = heap[i];
heap[i] = heap[smallest];
heap[smallest] = temp;
small_root_heapify(heap, smallest, heapsize) ;
}
}
EdgeNode removeMin(EdgeNode *heap, int heapsize)
{
EdgeNode min;
if (heapsize < 1)
printf("***heap underflow***");
min = heap[0];
heap[0] = heap[heapsize-1];
heapsize--;
small_root_heapify(heap, 0, heapsize);
return min;
}
以上随便写着玩的,
认真请看《算法设计与分析》