码迷,mamicode.com
首页 > 其他好文 > 详细

Heap & Heap Sort

时间:2021-05-24 12:49:42      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:最大值   接下来   str   heap   length   优先   转换   算法   完全   

---

What is a heap?

首先介绍优先队列

技术图片

Heap(堆)是对优先队列的一种实现

每个元素都有对应的key值,且对于大顶堆(Max Heap)而言,其每个元素的key值都 ≥ 子元素的key值

堆可以可视化为一棵完全二叉树:

技术图片

堆对应的树具有如下性质:(这里层数从0开始)

技术图片

别忘了之前讲过的完全二叉树的性质:n个结点的完全二叉树高度为 lgn

Max_heapify

技术图片

max_heapify() 只针对具有 “简单错位” 的堆进行调整,single violation是这里特别强调的一个前提条件,详见下

Pre_Condition

注意这里有个重要假设:

技术图片

  • 当对以 i 为根的子树进行 max_heapify() 操作时,结点 i左右子树均已经是大顶堆
  • 因此问题在于: 结点 i 并不是最大值却被放在了 level (lgn - 1) 层上(假设叶子为 level 0,从下往上数)。

那么 max_heapify() 的职责就很显然了:将最上面的结点 i 下沉到正确的位置

显然影响运行时长的因素在于 i 子树的层数,假设 i 子树深为 lgn,那么max_heapify() 的时间复杂度为O(lgn)

Build_Max_Heap(A)

我们已经知道 max_heapify() 严格要求了左右子树必须为大顶堆,那么对于一个完全乱序的数组A,显然直接调用max_heapify(A)是不允许的,这时要如何将其转换为大顶堆呢?

Algo

Build_Max_Heap(A)将通过多次调用 max_heapify() 将输入A 转换成一个大顶堆

由于叶子结点没有child,其本身已经是一个大顶堆,满足 single violation

所以我们可以跳过最下层的叶子,从 level 1 开始调用 max_heapify()

(level 1 为叶子结点之上的一层,即倒数第二层)

wait a moment:这里解释一下为什么要从下往上处理:

前面提到了使用 max_heapify() 的前提条件是左右子树已经为大顶堆,因此在倒数第二层调用显然是符合要求的(因为level 1中所有结点的左右子树均已经为大顶堆)

那么在这一层处理完毕后,所有“从level 1长出的子树均被调整为了大顶堆”,也就满足了接下来在level 2中调用max_heapify()的前置条件,以此类推...

接下来继续 Build_Max_Heap(A)的算法思路

我们已经解释了为何循环要从下至上处理,

for n/2 downto 1

不难看出,对于level 1的所有结点,最坏情况下的调整时间也只是O(1)

随着level向上增高,对level L层的结点进行max_heapify操作需要O(L)时间

最上层只有一个根结点,对它的调整需要O(lgn) ---(Tips: 复杂度源于)

将各层所需调整时间加起来可以得到整个算法的时间复杂度为O(n) ,步骤如下:

(括号内为一个收敛级数且收敛为常数)

技术图片

Build-Max-Heap Demo

给出一个乱序数组 A,通过 Build_Max_Heap(A)将其转化为大顶堆的步骤分解如下:

技术图片

技术图片

技术图片

Heap_Sort

技术图片

思路步骤:

  1. 首先将A转化为大顶堆
  2. 找到最大值,显然为 A[1]
  3. 将最大值与末尾元素交换,并将A[1]从堆中舍弃(数组length--)
  4. 对新的大小为 n-1的堆调用max_heapify方法将其调整为大顶堆(因为上一步中已经舍弃了最大值A[1],此时显然满足single violation的前提条件)
  5. 回到步骤2重复操作直到堆减为空,排序完毕

时间复杂度

整个算法的开头需要调用一次建立Build-Max-Heap(A) , --- O(n)

此后开始n次迭代: (第一次迭代确定了最大值,第二次确定次大值, ... ,n个数排序完毕需要迭代n次)

每次迭代包括一次swap操作和max_heapify() ---O(lgn)

因此总的时间复杂度为 O(n + nlgn) = O(nlgn)

Heap & Heap Sort

标签:最大值   接下来   str   heap   length   优先   转换   算法   完全   

原文地址:https://www.cnblogs.com/potofsalt/p/14773949.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!