排序算法之堆排序

堆排序是一种基于二叉堆数据结构的排序算法

二叉树:是 n(n >= 0)个结点的有限集合,该集合或为空集(空二叉树)。或者由一个根节点和两颗互不相交的,分别称为根节点的左子树和右子树的二叉树组成

 满二叉树:除了叶子节点,每个结点的度都是2。或者形象来讲,所有叶子节点都排满的二叉树

完全二叉树:节点排序顺序能够完全对应满二叉树的二叉树 

 既然完全二叉树是依序号排列,那么就可以用一维数组来保存,譬如

123456
[o][1][2][3][4][5]

两个重要推论:

1. 对于位置为 k 的节点,其左子节点 = 2 * k +1,右子节点 = 2 * k +2

2. 最后一个非叶子节点的位置 = (n / 2) - 1, n = 数组长度

二叉堆:一个完全二叉树的结构,同时又满足的性质(子节点的键值或者索引总是小于或大于其父节点)。根节点总是最大(最大堆)或最小(最小堆)

那么堆排序每次去取其根节点,就能得到最大值或者最小值,剩余节点再调整为二叉堆。如此往复,最终取得的节点就是有序的

以最大堆(升序排列)那么堆排序的流程总结为:

1. 将无序数组构建成 最大堆

2. 交换数组首元素 [0]  与 末尾元素 [arrayLen-1] 

3. 数组规模 -1,重新构建最大堆,如此重复

手动演示:

1. 无序数组 

356348986245311
[0][1][2][3][4][5][6][7]

2. 选择最后一个非叶子节点,开始往上构建最大堆

数组长度 / 2 - 1 = 8 /2 -1  = 3,对应元素为 9[3]

比较 9[3] 的左右子节点,与最大值交换;重复执行交换,最后构建出了最大堆

 

构建完成后,交换第一个元素与最后一个元素,这样最大值就放到最后

减少数组遍历的长度,继续构建,取出最大值

代码:

交换数组元素

void swap(int *array, int i, int j)
{
	int tmp = array[i];
	array[i] = array[j];
	array[j] = tmp;
}

打印数组,查看运行效果

void dispArray(int *array, int len, const char *desc)
{
	int i;
	
	printf("%s", desc);
	for(i=0; i<len; i++)
	{
		printf("%d ", array[i]);
	}
	printf("\n");
}

 构建最大堆

void buildMaxHeap(int *array, int len)
{
	int i;
	int lastNonLeaf = len/2 -1;
	
	for(i=lastNonLeaf; i>=0; i--)
	{
		ajustMaxHeap(array, len, i);
		dispArray(array, len, "Ajust Array:");
	}
}

调整最大堆,在根节点,其左右节点之间选择最大值,并且递归调整

void ajustMaxHeap(int *array, int len, int i)
{
	int maxIndex = i;
	int left = 2*i + 1;
	int right = 2*i + 2;
	
	// left child may the max num
	if(left < len && array[left] > array[maxIndex])
	{
		maxIndex = left;
	}
	
	// right child is the max num
	if(right < len && array[right] > array[maxIndex] && array[right] > array[left])
	{
		maxIndex = right;
	}
	
	if(maxIndex != i) // swap root <> child 
	{
		swap(array, i, maxIndex);
		dispArray(array, len, "===swap:");
		ajustMaxHeap(array, len, maxIndex); // it may broke ajusted heap, so ajust it
	}
}

 堆排序主框架,创建最大堆,取最大值,调整最大堆

void heapsort(int *array, int len)
{
	int i = len;
	
	buildMaxHeap(array, len);
	
	dispArray(array, len, "MaxHeap Array is:");
	
	// swap root node <> last node; array len--
	while(i)
	{
		swap(array, 0, i-1);
		dispArray(array, len, "swap root node, Array is:");
		
		i--;
		ajustMaxHeap(array, i, 0);
	}
}

 主函数,构建测试数组

int main(void)
{
	int array[] = {35,63,48,9,86,24,53,11};
	int len = sizeof(array) / sizeof(int);

	
	dispArray(array, len, "Orig Array is:");
	
	heapsort(array, len);
	
	dispArray(array, len, "New Array is:");
	
	return 0;
}

测试:

更多数据结构算法详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值