最小生成树---Kruskal




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;  
}  












以上随便写着玩的,

认真请看《算法设计与分析》


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值