排序算法之堆排序

堆排序

最差时间复杂度O(nlogn)
最优时间复杂度O(nlogn)
平均时间复杂度\Theta(nlog n)
最差空间复杂度O(n) total, O(1)auxiliary
堆排序 (Heapsort)是指利用 这种数据结构所设计的一种 排序算法 。堆积是一个近似 完全二叉树 的结构,并同时满足 堆积的性质 :即子结点的键值或索引总是小于(或者大于)它的父节点。——堆排序.维基百科


(图片引自维基百科)

个人理解的堆排序:欲对data[0,size)进行堆排序,1)对数组建大根堆(或小根堆),使之符合堆序性(父节点恒大于子节点)与结构性(完全二叉树);2)将根节点(最大元素)与未有序的最后一个节点i交换,交换后data[i,size)已有序;3)将根节点下滤以恢复大根堆的堆序性;4)回到步骤2),直至未有序部分只剩一个节点。

在建大根堆时,有两种方法:1)为满足堆序性从最后一个内部节点开始将全部内部节点下滤;2)从第一个节点开始将全部节点上滤以满足堆序性。其中,方法1)时间复杂度为∑height(i),方法二的时间复杂度为∑depth(i)。在二叉树结构中高度小(深度大)的节点更多,复杂度为高度和的方法1)在效率上更好一些。

算法代码:

inline int parent(int i) {return ((i) - 1) >> 1;}
inline int leftChild(int i) {return ((i) << 1) + 1;}
inline int rightChild(int i) {return ((i) << 1) + 2;}

void heapSort(int data[], int size)
{	/* 对data[]进行堆排序 */
	void buildMaxHeap(int[], int);
	void percolateDown(int[], int, int);

	/* 建大根堆 */
	buildMaxHeap(data, size);

	while (size)
	{
		/* 将第一个元素与未排序的最后一个元素交换 */
		int max = data[0];
		data[0] = data[size - 1];
		data[size - 1] = max;

		/* 将交换后的第一个元素下滤以恢复大堆堆序性 */
		percolateDown(data, --size, 0);
	}
}

void buildMaxHeap(int data[], int size)
{	/* 建大根堆 */
	void percolateDown(int[], int, int);

	/* 从最后一个内部节点开始,将所有内部节点下滤 */
	for (int i = parent(size - 1); i >= 0; i--)
	{
		percolateDown(data, size, i);
	}
}

void percolateDown(int data[], int size, int index)
{	/* 将序号为index的元素下滤以恢复大根堆堆序性 */
	int maxChild;
	int tmp = data[index];
	while (leftChild(index) < size)
	{
		maxChild = (rightChild(index) < size && data[leftChild(index)] < data[rightChild(index)]) ? rightChild(index) : leftChild(index);
		if (tmp >= data[maxChild])
		{
			break;
		}
		data[index] = data[maxChild];
		index = maxChild;
	}
	data[index] = tmp;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值