【算法导论】笔记-第五章 堆排序

第5章 堆排序

5.1 堆

  • 堆:(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树。

  • 最大堆性质:除了根以外的所有结点 i i i都要满足: A [ P A R E N T ( i ) ] > = A [ i ] A[PARENT(i)]>=A[i] A[PARENT(i)]>=A[i]

  • 最小堆性质:除了根以外的所有结点 i i i都要满足: A [ P A R E N T ( i ) ] < = A [ i ] A[PARENT(i)]<=A[i] A[PARENT(i)]<=A[i]

  • 结点的高度:该结点到叶节点最长简单路径上边的数目。

  • 常用表示:

    • 堆的结点数: h e a p s i z e = n heapsize=n heapsize=n

    • 堆的根结点个数: ⌊ n / 2 ⌋ \lfloor n/2\rfloor n/2

    • 堆的高度: ⌊ lg ⁡ n ⌋ \lfloor \lg n\rfloor lgn

    • 高度为 h h h的堆最多包含结点数: ⌈ n / 2 k + 1 ⌉ \lceil n/2^{k+1}\rceil n/2k+1

    • 父结点: i i i

    • 左子结点: 2 i 2i 2i

    • 右子结点: 2 i + 1 2i+1 2i+1

5.2 维护堆的性质

  • MAX-HEAPIFY是用于维护最大堆性质的重要过程。

  • 给定最大堆A中的一个元素i,它有可能不符合最大堆的性质,即A[i]有可能小于它的孩子,但是它的两棵子树已经满足了最大堆的性质。我们通过一个MAX-HEAPIFY过程来使得以A[i]为根的子树满足最大堆性质,MAX-HEAPIFY是通过让A[i]在最大堆中**“逐层下降”**来达成这一目标的。

  • 伪代码:MAX-HEAPIFY(A,i)

    l = LEFT(i)
    r = RIGHT(i)
    if l <= A.heap-size and A[l]>A[i]
        largest = l
    else largest = i
    if r<= A.heap-size and A[r]>A[largest]
        largest = r
    if larget != i
        exchange A[i] with A[largest]
        MAX-HEAPIFY(A,largest)
    
  • python代码:

    def max_heapify(A, i):
        heap_size = len(A)
        left = 2 * i
        right = 2 * i + 1
        if left <= heap_size and A[left] > A[i]:
            largest = left
        else:
            largest = i
        if right <= heap_size and A[right] > A[largest]:
            largest = right
        if largest != i:
            temp = A[largest]
            A[largest] = A[i]
            A[i] = temp
            max_heapify(A, largest)
        return A
            
    B = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1]
    k = 1
    print(max_heapify(B, k))
    
  • 运行时间: T ( n ) = O ( lg ⁡ n ) T(n)=O(\lg n) T(n)=O(lgn)

  • 时间复杂度: O ( h ) O(h) O(h)

5.3 建堆

  • 初始化:在第一次循环之前, i = ⌊ n / 2 ⌋ i=\lfloor n/2\rfloor i=n/2,而 i = ⌊ n / 2 ⌋ + 1 , i = ⌊ n / 2 ⌋ + 2 , ⋅ ⋅ ⋅ , n i=\lfloor n/2\rfloor+1,i=\lfloor n/2\rfloor+2,···,n i=n/2+1,i=n/2+2,,n都是叶结点,因而是平凡最大堆的根结点。

  • 保持:每次迭代维护这个循环的不变量,即满足最大堆性质。

  • 终止:过程终止时,满足最大堆性质。

  • 伪代码:BUILD-MAX-HEAP(A)

    A.heap-size = A.length
    for i = (A.length/2)的下界 downto 1
        MAX-HEAPIFY(A,i)
    
  • python代码:

    def build_max_heap(A):
        heap_size = len(A)
        for i in range(1, heap_size//2):
            max_heapify(A, i)
        return A 
            
    B = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1]
    print(build_max_heap(B))
    

5.4 堆排序算法

  • 步骤:

    • 将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
    • 将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
    • 将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
  • 伪代码:HEAPSORT(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)
    
  • python代码:

    def max_heapify(A, i):
        heap_size = A[0]
        left = 2 * i
        right = 2 * i + 1
        if left <= heap_size and A[left] > A[i]:
            largest = left
        else:
            largest = i
        if right <= heap_size and A[right] > A[largest]:
            largest = right
        if largest != i:
            temp = A[largest]
            A[largest] = A[i]
            A[i] = temp
            max_heapify(A, largest)
        return A
            
    def build_max_heap(A):
        heap_size = len(A)
        for i in range(1, heap_size//2):
            max_heapify(A, i)
        return A 
    
    def heapsort(A):
        build_max_heap(A)
        for i in range(len(A)-1, 1, -1):
            temp = A[1]
            A[1] = A[i]
            A[i] = temp
            A[0] = A[0] - 1
            max_heapify(A, 1)
        return A
            
    B = [10, 16, 4, 10, 14, 7, 9, 3, 2, 8, 1]
    print(heapsort(B))
    

5.5 优先队列(以最大优先队列为例,最小优先队列同理)

  • 优先队列:优先队列是一种用来维护由一组元素构成的集合S的数据结构。

  • 操作:

    • INSERT(S,x):把元素x插入集合S中, S = S ⋃ { x } S=S\bigcup \{x\} S=S{ x}
    • MAXIMUM(S):返回S中具有最大键字的元素。
    • EXTRACT-MAX(S):去掉并返回S中的具有最大键字的元素。
    • INCREASE-KEY(S,X,K):将元素X的关键字值增加到k。
  • 伪代码:

    • MAXIMUM(S)

      BUILD-MAX-HEAP(A)
      return A[1]
      
    • EXTRACT-MAX(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
      
    • INCREASE-KEY(S,X,K)

      if key < A[i]
          error"newe key is smaller than current key"
      A[i] = key
      while i>1 and A[PARENT(i)]

你可能感兴趣的:(算法导论,算法,数据结构,算法导论,堆排序)