堆排序

排序描述:

输入:n个数的序列<a1,a2,…,an>

输出:输入序列的一个重排<a’1,a’2,…,a’n>,使得, a’1a’2,≤。。。≤a’n

排序算法中一大类是比较排序,下面我就总结一下比较排序:

1.堆的概念和堆的性质

堆:是一个完全二叉树,除了最后一层外,其他层都是填满的。

如果用一个数组表示一个堆,需要两个性质:length[A]和heap-size[A]。length[A]表示数组A的总长度,heap-size[A]表示数组中堆元素的个数。树根为A[1],树中节点i有如下性质:

Parent(i)

 return i/2;

Left(i)

 return 2*I;

Right(i)

return 2*i+1;

最大堆:除了根节点外所有的节点满足 A[Parent(i)]≥A[i](节点的父节点不小于节点本身)

最小堆:除了根节点外所有的节点满足 A[Parent(i)]≤A[i](节点的父节点不大于节点本身)

(这里我们以最大堆为例子)

堆支持的操作如下:

MAX-HEAPIFY过程,其运行时间为O(lgn),是保持最大堆性质的关键

BUILD-MAX-HEAP过程,以线性时间运行,可以再无序的输入数组的基础上构造最大堆

HEAPSORT过程,运行时间为O(nlgn),对一个数组原地进行排序

MAX-HEAP-INSERT,HEARP-EXTRACT-MAX,HEAP-INCREASE-KEY和HEAP-MAXIMU过程的运行时间为O(lgn),可以让堆结构作为优先队列使用。

2.保持堆的性质(MAX-HEAPIFY)         

输入数组A和下标i,前提是Right(i)和Left(i)都已经是最大堆,而A[i]可能会违背最大堆的性质,所有需要调整。

MAX-HEAPIFY(A,i)

           l=Left(i)

           r=Right(i)

           if(l≤heap-size[A] and A[l]≥A[i])

                    then largest=l;

                    else largest=I;

           if(r≤heap-size[A] and A[r]≥A[largest])

                    then largest=r;

           if(largest!=i)

              then exchange A[i]<->A[largest]

              MAX-HEAPIFY(A,largest)

 

 举例说明一下:

在元素4所在位置A[2]位置处,我们调用HEAP-HEAPIFY(A,2),运行过程如下:

元素4首先与最大的孩子元素14交换,然后调用HEAP-HEAPIFY(A,4)

完成。

HEAP-HEAPIFY()的运行时间为:O(lgn)。

3,建堆

我们可以利用上面的HEAP-HEAPIFY()来进行建堆,我们从n/2+1处来调用上面的HEAP-HEAPIFY(),这样可以完成建堆,因为每一个叶子节点是平凡最大堆。

BUILD-MAX-HEAP(A)

  heap-size[A]<-length[A]

   for i<-length[A]/2 downto 1

      do MAX-HEAPIFY(A,i)

建立堆的例子:

A:[4,1,3,2,16,9,10,14,8,7]

开始状态:

首先从元素16开始,由于16大于他所有的子节点,所有,这里不再移动,接着就到元素2,调整结果为:

 

接着,到了元素3,进过调整为:

下面到元素1,调整后为:

 

到元素4,调整后为:

 

完成。

通过上面的步骤,我们可以猜测可能运行时间为O(nlgn),这个猜测不错,但是不够精确,其实其运行时间为O(n)(具体步骤证明可以参考算法导论P78)。

4,堆排序

基本思想:首先利用数字A构造一个最大堆,然后A[1]为最大元素,取出来,然后把A[heap-size]取代A[1],然后调用HEAP-HEAPIFY(A,1),递归返回A[1],就输出了排序后的数列。伪代码如下:

HEAP-SORT(A)

           BULID-MAX-HEAP(A)

     for i<-length[A] downto2

                    do exchange A[1]<-->A[i]

                      heap-size[A]<-heap-size[A]-1

                      MAX0HEAPIFY(A,1)

举例说明如下:

A:[4,1,3,2,16,9,10,14,8,7]

建堆过程在上面,我们这里直接引用结果:

第一次远行结果:

第二次运行结果:

第三次运行结果:

第四次运行结果:

第五次运行结果:

 

第六次远行结果:

第七次运行结果:

第八次运行结果:

第九次运行结果:

完成。

请注意,上面的九次步骤不是说这个算法的所有步骤,这里只是演示了排序过程,没有展示调整的过程。

运行时间为O(nlgn),以上就是所有的堆排序算法内容。

 

 

 

 

 

 

posted on 2012-06-04 21:57  lufangtao  阅读(446)  评论(0编辑  收藏  举报

导航