1.Heap
表示方法
满足以下性质的二叉树Binary Tree
可以成为Binary Heap
:
Complete Tree
:所有的层都是完全的,除了最后一层,且最后一层的叶子靠左。Min Heap or Max Heap
:根节点是最大值或者最小值,而且这个性质对于任何递归得到的子树都成立。
Binary Heap
通常使用array
表示:
- 根节点在
array[0]
; array[(i-1)//2]
返回父节点,array[2*i+1]
返回左孩子树,array[2*i+2]
返回右孩子树。
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