C++ 堆数据结构

程序中的堆存储区,是通过链表实现的。堆数据结构是一棵完全二叉树,对于最大堆来说,每个根节点的值不小于其子节点,也就是根节点,具有最大值。实际中可以用一个数组来表示完全二叉树,那么对于索引为 i 的节点来说,其左右子节点的索引分别为 2*i + 1 和 2*i + 2.

堆有两种操作:

1、上浮操作:在堆的末尾添加一个元素,然后使这个元素上浮,使维持堆结构。(也就是数组的某个元素的前边的所有元素都已经是堆结构,加入这个元素,调整,使维持堆结构)。

上浮的过程只需要和其父节点相比较。如果比其父节点大,上浮到父节点(最小堆);再和新位置的父节点相比较,这样进行下去:

 

void MaxHeapFixup(int arr[], int i)    //索引为i的元素的前边的所有元素已经满足堆结构
{
	if (i == 0)
		return;
	int temp = arr[i];
	int parent = (i - 1) / 2;     //父节点的索引
	while (parent >= 0)
	{
		if (arr[parent] <= temp)
			break;
		else
		{
			arr[i] = arr[parent];   //父节点往下覆盖  相当于空洞往上浮
			i = parent;
			parent = (i - 1) / 2;
		}
	}
	arr[i] = temp;   //最后填补空洞
}

2、下沉操作:下沉操作是某节点以下的所有元素都满足堆结构,需要使根节点下沉,使维持堆结构(也就是说数组的某个元素之后的所有元素都是堆结构,调整,使维持堆结构)。

下沉的过程因为是最大堆,需要和左右子节点的较大者交换,一直往下交换下去即可:

 

 

void MaxHeapFixdown(int arr[], int i, int len)   //索引为i的元素之后的所有元素  都满足堆结构   len表示数组的长度
{
	if (i == len - 1)
		return;
	int temp = arr[i];
	int child = 2 * i + 1;    //左子节点的索引
	while (child < len)
	{
		if ((child + 1 < len) && (arr[child + 1] > arr[child]))   //这里有个短路计算  如果没有右子节点 不会计算与运算右边的
			++child;
 		if (arr[child] <= temp)
			break;
		else
		{
			arr[i] = arr[child];     //往上覆盖   相当于空洞往下沉
			i = child;
			child = 2 * i + 1;
		}

	}
	arr[i] = temp;    //填补空洞
} 

 

构造一个最大堆:

对于叶子节点来说,由于没有子节点,已经满足堆结构,所以只需要从最后边一个非叶子节点往前进行下沉操作来调整,便可以构造一个堆出来。最后一个非叶子节点的索引为 len/2 - 1(归纳一下很容易得出)。

 

void MakeMaxHeap(int arr[], int len)    //len表示数组的长度
{
	for (int i = len / 2 - 1; i >= 0; --i)
	{
		MaxHeapFixdown(arr, i, len);
	}
}

堆排序就是借助堆这种数据结构进行排序。

对于一个长度为 len 的数组,由于是最大堆,索引为0 的元素是最大元素,且索引为 0 的元素后边的所有元素,都满足最大堆;如果将索引为 0 的元素与最后一个元素交换之后,那么前 len - 1 个元素除了第 0 个元素之外,都满足最大堆,这样对第 0 个元素进行下调操作;然后再将第0 个元素与倒数第2个元素交换..., 一直这样进行下去直到最后第 0 个元素都与后边所有的元素交换过,那么数组就是已经按照升序排好了。

 

 

void myHeapSort(int arr[], int len)   //最大堆的降序排序
{
	MakeMaxHeap(arr, len);   //先构造一个最大堆
	for (int i = len - 1; i >= 1; --i)
	{
		std::swap(arr[0], arr[i]);   //每次与 0 元素交换
		MaxHeapFixdown(arr, 0, i);    //重新交换到后边的元素之前的所有元素为堆
	}
}

 

或者这样,每次得到一个最大堆之后,索引为 0 的元素是最大元素;接着对后边的 元素进行最大堆调整,使索引为1的元素为后边的最大。。。这样一直到最后只剩下一个元素(STL中的partial_sort() 函数  就是这个原理):

 

void myHeapSort(int arr[], int len)   //最大堆的升序排序
{
    for(int i = 0; i < len; ++i)
    {
        MakeMaxHeap(arr+i, len - i);
    }
}

 

 

 

 

 

 

本文参考点击打开链接 感谢博主。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值