`
flforever1213
  • 浏览: 124764 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

算法 之 堆 - 排序

阅读更多

给出数组A[1...n],我们可以将其中的元素用下面的方法以非降序有效地排序。

首先将A变换成堆,并使其具有这样的性质:每个元素的键值是该元素本身,即key(A[i])=A[i],1 ≤ i ≤ n。

转换成堆之后,由于A中各项的最大值存储在A[1]中,可以将A[1]和A[n]交换,使得A[n]是数组中的最大元素。这时A[1]中的元素可能小于存放在它的一个子节点中的元素,于是用过程Sift-down将A[1...n-1]转换成堆。接下来将A[1]和A[n-1]交换,并调整数组A[1...n-2]成为堆。交换元素和调整堆的过程一直重复,直到堆的大小变成1为止,这时,A[1]是最小的。

 

过程  HeapSort

输入  n个元素的数组A[1...n]

输出  以非降序排列的数组A

 

算法描述

for j ← n downto 2

    互换 A[1]和A[j]

    Sift-down(A[1...j-1], 1)

end for

 

注意这里算法描述的数组的索引都是1...n,而不是大家习惯的0...n-1。

 

创建堆需要Θ(n)的时间,Sift-down运算需要O(log n)时间,并且要重复n-1次,也就是用该算法给n个元素排序需要时间O(n log n)。 

// heap[0]用来存储数组中堆数据的长度,堆数据heap[1]...heap[heapLength]
// 所以数组的实际长度是heapLength+1,我们只对从数组索引为1开始的heapLength个数据进行操作

void siftDown(int* heap, int siftDownTo, int index)
{
	if (index < 1 || index * 2 > siftDownTo)
		return;

	bool done = false;
	while(!done && index * 2 <= siftDownTo)
	{
		index *= 2;

		if (index + 1 <= siftDownTo && heap[index + 1] > heap[index])
			index += 1;

		if (heap[index] > heap[index / 2])
		{
			int temp = heap[index];
			heap[index] = heap[index / 2];
			heap[index / 2] = temp;
		}
		else
		{
			done = true;
		}
	}
}

void heapSort(int* heap)
{
	if (heap == NULL)
		return;

	int heapLength = heap[0];
	int temp = 0;

	for (int i = heapLength; i >= 2; i--)
	{
		temp = heap[1];
		heap[1] = heap[i];
		heap[i] = temp;

		siftDown(heap, i - 1, 1);
	}
}

 

我使用的数组是这样定义的:

const int HEAP_LENGH = 10;
int heap[HEAP_LENGH + 1] = { HEAP_LENGH, 20, 11, 9, 10, 5, 4, 5, 3, 7, 3 }; 
heapSort(heap);

 

更多内容请参考:

算法 之 堆 - 简介

算法 之 堆 - Sift-up和Sift-down

算法 之 堆 - 插入和删除

算法 之 堆 - 创建堆

3
6
分享到:
评论
2 楼 flforever1213 2011-03-16  
onewind 写道
void heapSort(int* heap)中缺少了建堆的代码了吧。。。

这个在另一篇文章中啊,一篇文章太长了不好看,我分开写了。。
1 楼 onewind 2011-03-16  
void heapSort(int* heap)中缺少了建堆的代码了吧。。。

相关推荐

Global site tag (gtag.js) - Google Analytics