堆排序

      顾名思义,堆排序算法使用堆来排序无序的anarray数组。首先,算法将数组转换为堆。为完成转换,一种方法是使用heapInsert函数,将项逐一入堆。
      还有一种方法有数组anArray的项构建堆,这种方法的效率更高。假设anArray的原始内容如图1-a所示。将数组anArray的项指派给树的节点,从根开始,从左到右,逐渐下移将数组视为二叉树。结果如图1-b所示。此后,反复调用heapRebuilt,将该树转换为堆。heapRebuilt将半堆转换为堆。半堆的子树为堆,但根为就位。但是,树中有供heapRebuilt处理的半堆吗?图1-b的树不是半堆,但查看叶子,可以找到半堆;换言之,每个叶子是一个半堆。首先从左到右在叶子上调用heapRebuilt,接着沿树上移,在到达节点s时,其子树为堆。于是,heapRebuilt将以s为根的半堆转换为堆。

                                             
                                                 图1 (a)anArray的原始内容 ;(b)anArray的相应二叉树
     下面的算法将包含n个项的anArray数组转换为堆,这是堆排序算法的第一个步骤。

for(index=n-1  down to 0)
{
	//Assertion :the tree rooted at index is a semiheap
	heapRebuild(anArray,index ,n);
	//Assertion :the tree rooted at index is a heap;
}


      实际上,在前面的for语句中,可用n/2替换n-1。(因为从n/2到n-1的节点都为叶子,已经是堆了,没有必要在调用heapRebuilt函数)。图2跟踪图1-a的数组的算法。                                                                                                                                                                                                                                     

                                                                  图2 将anArray数组转换为堆
       将数组转换为堆之后,堆排序将数组分为两个区域:heap(堆)和Sorted(有序),如图3所示,Heap区域在anArray[0..last],Sorted区域anArray[last..n-1]。开始时,Heap区域包含anArray的所有内容,而sorted区域为空,换言之,last=n-1。

                          
                                                             图3  堆排序将数组分成两个区域
     在算法的每一步,将项I从heap区域移到Sorted区域。堆排序算法的不变式为:
                              * 在步骤K后,Sorted区域包含anArray的K个最大值,且有序,换言之,anArray[n-1]是最大值,anArray[n-2]是第二最大值,以此类推。
                              * Heap区域中的项构成堆。
     只要保持不变式,I必然是Heap区域中的最大项,故必为堆的根。为完成移动,交换堆的根项与堆的最后一项,换言之,交换anArray[0]与anArray[last],然后last的值减1。结果,移动后,将Heap区域转换为堆,因为新项可能位置不对。可用heapRebuilt下移根项,是Heap区域再一次构成堆。
下面的伪码总结这些步骤:

heapSort(inout anarray:ArrayType ,in n:integer)
//sorts anarray[0..n-1]
{
	//build intial heap
	for(int index=n/2;index>=0;i--)
	{
		heapRebuild(anarray,index,n);
	}
	//Assertion :anArray[0]is the largest item in heap
	//anArray[0..n-1];
	last=n-1;
	//Invariant :anarray[0..last] is a heap
	//anArray[last+1,n-1] is sorted and contains the largest items of 
	//anArray
	for(int step=1 ;step<n;step++)
	{
		//move the largest item in the heap region --that
		//is ,the root anArray[0] --to the begining of the
		//Sorted region by swapping items;
		Swap anarray[0]  and anarray[last];
		Decrement last;
		//make the heap region a heap again
		heapRebuild(anarray,0,last);
	}

}

      堆排序的效率分析与归并相似,在最坏的情况及平均情况下,两种算法均为O(n*log n)。与归并排序相比,堆排序的优势在于不需要第二个数组。快速排序在平均情况下也O(n*log n),但在最坏的情况下为O(n^2)。尽管在最坏的情况下的效率不高,快速排序任然为首选的排序方法。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值