《算法导论》笔记 第6章 6.2保持堆的性质
【笔记】
当 MAX_HEAPIFY(A, i) 被调用时,我们假定LEFT(i)、RIGHT(i)为根的两棵二叉树都是最大堆。
若子结点中有最大元素,将 A[i] 与其交换,对该子树调用 MAX_HEAPIFY。若 A[ i ] 为最大元素,结束循环。
MAX_HEAPIFY 作用于一个高度为 h 的结点所需的运行时间为 O(h)。
void maxHeapify(int i) { int l = left(i); int r = right(i); int largest = i; if (l <= heapSize && A[l] > A[largest]) largest = l; if (r <= heapSize && A[r] > A[largest]) largest = r; if (largest != i) { swap(A[i],A[largest]); maxHeapify(largest); } }
【练习】
6.2-1 图示出MAX_HEAPIFY(A,3)作用于数组A=<27,17,3,16,13,10,1,5,7,12,4,8,9,0>的过程。
6.2-2 由过程MAX_HEAPIFY开始,写出进行对应的最小堆操作的MIN_HEAPIFY(A,i)过程的伪代码,并比较MIN_HEAPIFY与MAX_HEAPIFY的运行时间。
void minHeapify(int i) { int l = left(i); int r = right(i); int smallest = i; if (l <= heapSize && A[l] < A[smallest]) smallest = l; if (r <= heapSize && A[r] < A[smallest]) smallest = r; if (smallest != i) { swap(A[i],A[smallest]); minHeapify(smallest); } }
运行时间相同。
6.2-3 当元素 A[ i ] 比其两子女的值都大时,调用 MAX_HEAPIFY(A,i) 的效果是什么?
不进行操作,程序结束。
6.2-4 对 i > heap_size[A]/2,调用 MAX_HEAPIFY(A,i)的结果怎样?
由6.1的证明可知,i是叶子结点,当i没有子结点时,程序结束。
6.2-5 MAX_HEAPIFY的代码效率较高,但第十行中的递归调用可能例外,它可能使某些编译程序产生出低效的代码。请用迭代的控制结构(循环)取代递归结构,从而写一个更为高效的MAX_HEAPIFY。
void maxHeapify_NonRecursive(int i) { while (true) { int l = left(i); int r = right(i); int largest = i; if (l <= heapSize && A[l] > A[largest]) largest = l; if (r <= heapSize && A[r] > A[largest]) largest = r; if (largest == i) break; swap(A[i],A[largest]); i = largest; } }
设有n个结点的堆高度为h。由堆的定义可知,根节点到叶子结点最多比较 h 次,即 logn 次。
因此最坏运行时间为Ω(lgn)。