堆的下标相关:
对于大小为n的堆(0~n-1)中的一个元素idx
(1)左孩子:idx*2 + 1
(2)右孩子:idx*2 + 2
(3)父亲结点:(idx-1)/2
(4)最大(右下)的非叶子结点:n/2-1
特别注意(4)区别于(3),为什么呢?最后一个结点为n-1,那么它的父亲结点肯定是最后一个非叶子结点。即(n-1-1)/2 = n/2 - 1,都是下标搞的麻烦是吧!
目的:通过n/2-1次调整堆,可以构造一个堆。
调整堆(i,max):将i及之后(右、下)的元素调整到合适堆的位置。
思路:选三者最大:idx, 左, 右。交换idx和最大的那个,然后递归调整所有右、下的元素(以large为下次递归的idx)。
构造堆:倒着,将所有非叶子结点(i
调整堆(最朴素的递归方法):
//adjust heap() void heapify(TYPE* heap, int idx, int n) { //left and right index int left = 2 * idx + 1; int right = 2 * idx + 2; int large = 0; //Check left if(left<n && heap[left]>heap[idx]) { large = left; } else { large = idx; } //Check right if(right<n && heap[right]>heap[large]) { large = right; } //Swap idx and max one if(idx!=large) { swap(&heap[idx], &heap[large]); heapify(heap, large, n); } }
构造堆:
void buildHeap(TYPE* heap, int n) { int i=n/2-1; for(; i>=0; i--) { heapify(heap, i, n); } }