算法导论之五堆排序

堆排序的时间复杂度是,与插入排序相似,堆也具有空间原址性,即任何时候都只需要常数个额外的元素空间存储临时数据。

1.        堆简介:

(1)堆是一个数组,表示堆的数组A包括两个属性:A.length表示数组元素的个数,A.heap-size表示有多少个堆元素存储在该数组中。

给定一结点的下标i,可以得到其父结点、左孩子和右孩子的下标:

PARENT(i)

return

 

LEFT(i)

return 2i

 

RIGHT(i)

return 2i+1

 

(2)最大堆性质是指除了根以外的所有结点i都要满足:A[PARENT(i)] >=A[i],即某个结点的值最多与其父结点一样大。

堆中的结点高度为该结点到叶结点最长简单路径上边的数目。包含n个元素的堆看做一棵完全二叉树时,其堆高度为。

2.        维护堆性质

MAX-HEAPIFY是用于维护最大堆性质的过程,输入为一个数组A和一个下标i。该过程通过对A[i]的值在最大堆中“逐级下降”,从而使得以下标i为根结点的子树重新遵循最大堆的性质。

MAX-HEAPIFY(A,i)

         l = LEFT(i)

         r = RIGHT(i)

         //选出最大结点,将其下标存储在largest中

         if l <= A.heap-sizeand A[l] > A[i]

                   largest = l

         else largest = i

         if r <= A.heap-sizeand A[r] > A[largest]

                   largest = r

         //如果A[i]最大,则以i为根结点的子树已经是最大堆,程序结束

         if largest != i

                   exchangeA[i] with A[largest]  //否则交换二值

//交换后,下标为largest的结点的值为原来的A[i],以此节点为根的子树有可能会//违反最大堆的性质,因此需要对子树递归调用

                   MAX-HEAPIFY(A,largest)         

注意该过程的时间复杂度为,即与树高呈线性关系。

3.        建堆

采用自底向上的方法利用过程MAX-HEAPIFY可将一个大小为n=A.length的数组A[1..n]转换为最大堆。过程BUILD-MAX-HEAP对树中的其他结点都调用一次MAX-HEAPIFY。

BUILD-MAX-HEAP(A)

         A.heap-size = A.length

         for i =  downto 1          //由于A(+1..n)中的元素都是树的叶节点

                   MAX-HEAPIFY(A,i)

注意每一次for循环的开始,结点i-1,i-2,…,1都是一个最大堆的根结点。

4.        堆排序算法

堆排序利用BUILD-MAX-HEAP将输入数组A[1..n](n=A.length)建成最大堆,因为数组中的最大元素总在根结点A[1]中,通过把它与A[n]交换,让该元素放到正确的位置。此时,从堆中去掉结点n,剩余的结点中,原来根的孩子仍然是最大堆,而新的根结点可能会违背最大堆的性质,因此,调用MAX-HEAPFY(A,1),从而在A[1..n-1]上构造一个新的最大堆。以此不断重复该过程。

HEAP-SORT(A)

         BUILD-MAX-HEAP(A)

         for i =A.length downto 2

                  exchange A[1] with A[i]

                   A.heap-size= A.heap-size – 1

                  MAX-HEAPIFY(A,1)

注意HEAP-SORT的时间复杂度为。

5.        堆的应用:优先队列

优先队列是一种用来维护由一组元素构成的集合S的数据结构,其中每一个元素都有一个相关的值,称为关键字。最大优先队列的应用之一是共享计算机系统的作业调度,而最小优先队列应用之一是基于事件驱动的模拟器。下面介绍最大优先队列的集中操作。

HEAP-MAXIMUM(A)        //返回最大关键字的元素

         return A[1]

 

HEAP-EXTRACT-MAX(A)  //去掉并返回S中具有最大关键字的元素

if A.heap-size < 1

                  error "heap underflow"

max = A[1]

A[1] = A[A.heap-size]

A.heap-size = A.heap-size -1

MAX-HEAPIFY(A,1)

return max

 

HEAP-INCREASE-KEY(A,i,key)  //将元素i的关键字值增加到key

         if key <A[i]

                   error"new key"

         A[i] = key

         while i >1 and A[PARENT(i)] < A[i]

                   exchangeA[i] with A[PARENT(i)]

                   i =PARENT(i)

 

MAX-HEAP-INSERT(A,key)                 //实现INSERT操作

         A.heap-size =A.heap-size + 1

         A[A.heap-size]= -

         HEAP-INCREASE-KEY(A,A.heap-size,key)

 

下面的程序是实现最大堆排序:

voidbuild_max_heap(int *a,int len);

voidheap_sort(int *a,int len);

 

#include<stdio.h>

voidexchange(int *a,int i,int j)

{

         a[i]^=a[j];

         a[j]^=a[i];

         a[i]^=a[j];

}

 

intleft_child(int i)

{

         return (2*(i+1)-1);

}

 

intright_child(int i)

{

         return (2*(i+1)+1-1);

}

 

voidmax_heapify(int *a,int len,int index)

{

         int l,r;

         int largest=index;

 

         l=left_child(index);

         r=right_child(index);

 

         if ((l<len) &&(a[l]>a[largest]))

         {

                   largest=l;

         }

         if ((r < len) && (a[r] >a[largest]))

         {

                   largest=r;

         }

 

         if (largest != index)

         {

                   exchange(a,largest,index);

                   max_heapify(a,len,largest);

         }

}

 

 

intmain()

{

         int source[]={16,4,10,14,7,9,3,2,8,1};

         exchange(source,0,1);

         printf("%d%d",source[0],source[1]);

         printf("\n");

         int i;

 

         heap_sort(source,sizeof(source)/sizeof(source[0]));

 

         for(i=0;i<sizeof(source)/sizeof(source[0]);i++)

         {

                   printf("%d",source[i]);

         }

         printf("\n");

}

 

voidbuild_max_heap(int *a,int len)

{

         int i;

 

         for (i=len/2;i>=0;--i)

         {

                   max_heapify(a,len,i);

         }

 

         for (i=0;i<len;i++)

         {

                   printf("%d ",a[i]);

         }

         printf("\n");

}

 

voidheap_sort(int *a,int len)

{

         int i;

         build_max_heap(a,len);

         for (i=len-1;i>=1;--i)

         {

                   exchange(a,0,i);

                   max_heapify(a,i,0);

         }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mengrennwpu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值