算法导论--第六章--堆排序

6.1 认识堆

1.(二叉)堆是一个数组,他可以被看成一个近似的完全二叉树。表示堆的数组A包括两个属性:A.Length给出数组元素的个数(数组的长度,有的元素中可能没有存值),A.heap-size表示有多少个堆元素存储在该数组中。这里0=<A.heap-size=<A.Length:就是说,虽然A[1..A.Length]可能都存有数据,但只有A[1..A.heap-size]中存放的时堆中的有效数据。

2.树的根节点是A[1]。这样给定一个节点下表 i ,很容易表示其父节点、左孩子、右孩子分别为:return A[i/2] 向下取整、return 2*i、return 2*i + 1.

3.堆氛围最大堆和最小堆。最大堆中除了根节点外,所有的元素都要满足:A[PARENT(i)]>=A[i];最小堆正好相反,除了根节点外多有节点 i 都有A[PARENT(i)] =< A[i]。在排序中我们使用的是最大堆。最小堆通常用于构造优先队列。

4.树的高度定义为根节点到叶节点最长简单路径上的数目;所以一个节点的高度为该节点到叶子节点最长简单路径上边的数目。该堆的高度为lgN。堆上的一些基本操作至多与树的高度成正比,即时间复杂度为LgN。

6.2  维护堆的性质

1.MAX-HEAPIFY过程是用于维护最大堆性质的重要过程。他的输入为一个数组A和一个下表 i ,期中 i 表示新节点插入堆的位置。调用的时候,我们假定根节点的LEFT(I)、RIGHT(I)的二叉树都是最大堆,但A[i]有可能小于其孩子,这就违背了最大堆的性质。此时我们让A[i] 逐层下降,来维护最大堆的性质。

2.MAX-HEAPIFY过程的伪代码如下:时间复杂度为LgN,即树的高度  h

MAX-HEAPIFY(A,i )

1,l = LEFT(i)

2,r = RIGHT(i)

3,if l =< A.heap-size and A[l] >A[i]    //先和左孩子节点比较大小,注意到叶子节点截止

largest = l

       else largest = i

4,if r=< A.heap-size and A[r]>A[largest]//与右孩子节点比较

largest = r

5,if largest is not equal i    //largest   的值不是 i 说明A[i] 破坏了最大堆的性质,交换并递归调用MAX-HEAPIFY(A,i)

exchange A[i] with A[largest]

MAX-HEAPIFY(A,largest)


6.3  建堆   时间复杂度O(h)

一个拥有n个节点的堆,画出其完全二叉树后知道,子数组A[n/2 + 1..n]中的元素都是树的叶子节点,所以我们不需要维护。下面通过BUILD-MAX-HEAP对树中的其他节点都调用一次MAX-HEAPIFY,既可以得到一个最大堆(通过一步步维护堆的性质,来建堆)

BUILD-MAX-HEAP(A)

1,A.heap-size = A.length

2,for i = A.length/2   downto 1  //从第一个不是叶子节点的节点开始,进行建堆(即逐步维护)。刚开始看成是一个最大堆,然后再一个一个的来维护

MAX-HEAPIFY(A,i)


6.4 通过前面的建堆,现在我们可以在此基础上进行排序。即构建最小堆。构建好的最小堆就是我们想要的从小到大的排序序列。  时间复杂度 O(nlgn)

HEAPSORT(A)

1, BUILD-MAX-HEAP(A)

2, for i=A.lenght downto 2

2,exchange A[1] with A[i]//将最大堆上面最后一个元素和对顶元素进行交换,逐步的交换

4,A.heap-size = A.heap-size -1

5,  MAX-HEAPIFY(A,1)   //因为每次都是讲堆顶元素换成新的数据,有可能破坏了最大堆的性质,所以我们需要进行维护。

至此,我们通过建最大堆,然后通过虚拟的摘堆,就可以将其进行堆排序!



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值