《算法导论》笔记 第6章 6.4堆排序算法
【笔记】
反复将大根堆的根与最后一个结点交换,堆的大小减一,对根结点执行MAX_HEAPIFY维护堆的性质。
最终 A 数组按升序排列。
void heapSort() { buildMaxHeap(); for (int i=length;i>=2;i--) { swap(A[1],A[i]); heapSize--; maxHeapify(1); } }
【练习】
6.4-1 说明 HEAPSORT 在数组 A = <5,13,2,25,7,17,20,8,4> 上的操作过程。
A = <2,4,5,7,8,13,17,20,25>
6.4-2 讨论在使用如下循环不变式时,HEAPSORT的正确性:
在每次for循环的迭代开始时,
子数组A[1..i]是一个包含了A[1..n]中的i个最小元素的最大堆;
而子数组A[i+1..n]包含了已排序的A[1..n]中的n-i个最大元素。
初始化:在第一轮迭代之前,i = n,A[1..n]是包含前n个最小元素的最大堆;子数组A[n+1..n]中没有元素,即已排好序的0个最大元素。
保持:将A[1..i]个包含了A[1..n]中的最小i个元素中的最大元素移动到 A[i],由于 A[i]>=A[1..i-1],A[i]<=A[i+1..n],因此A[i..n]包含了已排序的A[1..n]中的n-i+1个最大元素。
对新的根结点执行MAX_HEAPIFY保持堆的性质,因此A[1..i-1]是一个包含了A[1..n]中的i-1个最小元素的最大堆。
for 循环中递减i,为下一次迭代重新建立了循环不变式。
终止:过程终止时,i=1。根据循环不变式,我们知道A[2..n]包含了已排序的n-1个最大元素。A[1]是A[1..n]中最小的元素。
因此A[1..n]是一个已排好序的数组。
6.4-3 对一个其所有n个元素已按递增序排列的数组A,堆排序的运行时间是多少?若A的元素成降序呢?
当A升序排列时:
执行BUILD_MAX_HEAP建堆,时间 O(n)。 循环调用MAX_HEAPIFY维护堆,时间 O(n)*O(logn),总复杂度O(nlogn)。
当A降序排列时,与升序排列相同。
6.4-4 证明:堆排序的最坏情况运行时间为Ω(nlogn)。
引用别人家的证明:
*6.4-5 证明:在所有元素都不相同时,堆排序的最佳运行时间是Ω(nlogn)。