算法技术手册 - 排序 - 堆排序 - 调整堆和构造堆

堆的下标相关:

对于大小为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);
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *