Heap Sort 的原理及Python实现

1.Heap表示方法

满足以下性质的二叉树Binary Tree可以成为Binary Heap

  1. Complete Tree:所有的层都是完全的,除了最后一层,且最后一层的叶子靠左。
  2. Min Heap or Max Heap:根节点是最大值或者最小值,而且这个性质对于任何递归得到的子树都成立。

Binary Heap通常使用array表示:

  1. 根节点在array[0];
  2. array[(i-1)//2]返回父节点,array[2*i+1]返回左孩子树,array[2*i+2]返回右孩子树。

img
Binary Heap通常使用array表示,对于任意索引i

def parent(i):
    return (i-1)//2
def left(i):
    return 2*i+1
def right(i):
    return 2*i+2

2.Max-Heapify

max heapify是保持max-heap性质的操作,输入为array A and index i,假设输入时,以left(i) and right(i)为根节点的子数都满足最大堆性质,但是以i为根节点的子数不满足最大堆性质。max heapify函数让A[i]向下层转移,进行调整。

def MaxHeapify(array,i):
    l = left(i)
    r = right(i)
    largest = i
    if l<=len(array) and array[l]>array[i]:
        largest = l
    if r<=len(array) and array[r]>array[i]:
        largest = r
    if largest != i:
        array[largest],array[i] = array[i],array[largest]
        MaxHeapify(array,largest)

时间复杂度分析:

在一个以i作为根节点、包含n个节点的子数上运行MaxHeapify的时间包含:调整largest常数时间,孩子子树运行MaxHeapify的时间。由于孩子子数最多有2n/3个节点(这种情况只会发生在最底层节点刚好是 half full 的情况),因此可以描述为以下形式:

$ T(n)\leq T(2n/3)+\Theta(1)$

按照公式法可以得到时间复杂为O(lgn)

3.Build-Max-Heap

MaxHeapify前提条件是以left(i) and right(i)根节点的子数都是满足最大堆性质的,那么显然如果我们从最底层的子数开始,逐渐往上,对每个节点执行MaxHeapify(array,i)操作,那么这个堆所有的节点都满足最大堆性质,变为最大堆。但是,如果我们从最上层开始执行MaxHeapify,那么显然不满足前提条件。

另外具体从哪个节点开始呢,heap有个性质,对于array[0,1,...,n-1]的数组,array[(n-1)//2+1:n-1]的节点全是叶节点,而叶节点是不需要MaxHeapify操作的,所以我们只对array[:(n-1)//2]的元素进行操作:

def BuildMaxHeap(array):
    for i in reversed(range((len(array)-1)//2+1)):
        MaxHeapify(array,i)

计算得到BuildMaxHeap的时间复杂度为O(n),也就是说堆的建立是线性时间,而不是O(nlgn),这是堆相对于普通排序最大的优点之一。

4.HeapSort

heapsort的时间复杂度为O(nlgn),而且是就地排序算法,除输入数组只外只占用恒定的内存空间,这兼具了insertion sort(就地排序)和merge sort(时间复杂度)的优点。

def MaxHeapify(array,n,i):
    l = 2*i+1
    r = 2*i+2
    largest = i
    if l<=n and array[l]>array[largest]:
        largest = l
    if r<=n and array[r]>array[largest]:
        largest = r
    if largest != i:
        array[largest],array[i] = array[i],array[largest]
        MaxHeapify(array,n,largest)

def HeapSort(array):
    n = len(array)
    for i in reversed(range(n//2)):
        MaxHeapify(array,n-1,i)
    for i in reversed(range(1,len(array))):
        array[i],array[0] = array[0],array[i]
        n -= 1
        MaxHeapify(array,n-1,0)
    return array

猜你喜欢

转载自blog.csdn.net/weixin_37621790/article/details/86695537