C语言 堆排序算法

各个函数的功能: 

  1. maxHeapify 的参数为数组 a 和需要操作的下标 i。在调用 maxHeapify 的时候,需要确保根节点为 LEFT(i) 和 RIGHT(i) 的二叉树都是最大堆。若 a[i] 小于其孩子,则让 a[i] 的值在最大堆中逐级下降,从而使得以下标 i 为根节点的子树遵循最大堆的性质。若 a[i] 大于其孩子,那么无需进行任何操作。
  2. buildMaxHeap 的参数为数组 a 和数组长度 length。不难知道数组 a[length/2, length-1] 中的元素都是树的叶结点,而这些叶结点都可以看作是只包含一个元素的最大堆。这个性质让所有叶结点的父结点都满足了 maxHeapify 函数的使用条件,从而可以让我们自下而上地对树中的其他结点都调用一次 maxHeapify 函数,使得整棵树成为最大堆。
  3. heapSort 的参数为数组 a 和数组长度 length。首先调用 buildMaxHeap 将数组转换为最大堆,由最大堆的性质可知,根节点的值必然是整棵树的最大值。我们将根节点的值与数组的最后一个元素交换,就可以把最大值放在数组最后面。减少堆中的元素的数量,这时新的根节点有可能不满足最大堆的性质,所以需要调用 maxHeapify 确保整棵树仍然满足最大堆的性质。递归地重复上述过程,一直把新的最大值放到数组最后面,就可以得到一个排序好的数组。
// 堆排序

#include <stdio.h>

#define SWAP(a,b) {a=a^b; b=a^b; a=a^b;}
#define LEFT(i) ((i+1)*2-1)
#define RIGHT(i) ((i+1)*2)

void maxHeapify(int* a, int length, int i);
void buildMaxHeap(int* a, int length);
void heapSort(int* a, int length);

int main(void)
{
	int a[] = { 4,1,3,2,16,9,10,14,8,7,18 };
	int length = sizeof(a) / sizeof(a[0]);
	
	printf("排序前:");
	for (int i = 0; i < length; i++)
		printf("%d ", a[i]);
	printf("\n");

	heapSort(a, length);

	printf("排序后:");
	for (int i = 0; i < length; i++)
		printf("%d ", a[i]);

	return 0;
}

void maxHeapify(int* a, int length, int i)
{
	int l = LEFT(i);
	int r = RIGHT(i);
	int largest;

	if (l < length && a[l] > a[i])
		largest = l;
	else
		largest = i;
	if (r < length && a[r] > a[largest])
		largest = r;

	if (largest != i)
	{
		SWAP(a[i], a[largest]);
		maxHeapify(a, length, largest);
	}
}

void buildMaxHeap(int* a, int length)
{
	for (int i = length / 2; i >= 0; i--)
		maxHeapify(a, length, i);
}

void heapSort(int* a, int length)
{
	buildMaxHeap(a, length);
	for (int i = length - 1; i > 0; i--)
	{
		SWAP(a[0], a[i]);
		maxHeapify(a, --length, 0);
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值