堆排序

/**
堆:是一棵完全二叉树,并且满足父母优势原则(每个结点的键值都要大于等于它子女的键值,对于叶子结点该条件默认满足)。
数据结构:通常用数组来表示,a[0...n-1]表示表示有n个结点的一棵完全二叉树,点a[i]的左右孩子分别为a[2*i+1]和a[2*i+2]。
构造堆的方式有两种:
1.自底向上:从最后一个父母结点(a[n/2-1])开始,到树根(a[0])为止,检查这些结点是否满足父母优势原则,若不满足则调整(注意:调整后,要再次对与其交换的子女结点进行调整,直到满足父母优势)
2.自顶向下:依次插入新结点到已经构造好的堆中(插到最后一个),再重新构造堆,方法是将新结点与其父母比较,若大于其父母的键值则交换(一直执行该操作直到满足父母优势,此时则新加入的结点被插入到了合适的位置)
时间复杂度:
方式1:可以证明,对于n个结点,构造堆只需不到2n次比较就能完成。
方式2:构造堆的复杂度为O(n*logn)。
堆的插入和删除操作的时间复杂度都属于O(logn)
**/

/* 调整堆。
   以root为根的子树原本是一个堆,在对root进行修改后,就要从root开始检测,
   若父母优势条件已被破坏则进行调整。可以用递归实现,也可以用非递归		*/
void heapAdjust(int a[], int root, int len)
{
	int maxIndex = root;
	while (2*root + 1 < len)
	{
		if (a[2*root+1] > a[maxIndex])
			maxIndex = 2*root + 1;
		if (2*root+2 < len && a[2*root+2] > a[maxIndex])
			maxIndex = 2*root + 2;
		if (maxIndex != root)
		{
			swap(a[root], a[maxIndex]);
			root = maxIndex;
		}
		else
			break;
	}
}

/* 递归实现的“调整堆” */
void heapAdjustRec(int a[], int root, int len)
{
	if (2*root + 1 >= len)
		return;
	int maxIndex = root;
	if (a[2*root+1] > a[maxIndex])
		maxIndex = 2*root + 1;
	if (2*root+2 < len && a[2*root+2] > a[maxIndex])
		maxIndex = 2*root + 2;
	if (maxIndex != root)
	{
		swap(a[root], a[maxIndex]);
		heapAdjust(a, maxIndex, len);
	}
	else
		return;
}

/* 堆排序。参数为待排序的数组 a[0...n-1] */
void heapSort(int a[], int n)
{
	for (int i = n/2-1; i >= 0; i--) // 采用自底向上的方式构造堆
		 heapAdjust(a, i, n);

	for (int i = n-1; i > 0; i--)
	{
		 swap(a[0], a[i]);
		 heapAdjust(a, 0, i);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值