堆排序

堆,分为大根堆和小根堆。大根堆是一颗父节点的值大于孩子节点的值的完全二叉树,小根堆反之。

堆排序,是一种选择排序。它的最好最坏和平均时间复杂度均为O(nlgn)。

堆排序是不稳定的排序。

堆排序主要分为两个过程:1.建堆;2.调整堆。

例:

134253

数组a[] = {1, 3, 4, 2, 5, 3}, 首先建一个堆。根据调整,使其满足大根堆,a[i] >= a[i*2+1] && a[i] >= a[i*2+2]。

    经过调整变成堆  

此时,堆顶元素即a[0], 为最小的数。

然后把a[0],和最后一个元素交换,将a[0...n-2]调整为堆。

   

调整完成后,堆顶元素为a[0...n-2]里最小的数,再讲a[0]和a[n-2]交换,继续调整a[0...n-3]。

        

重复以上步骤

       



经过n-1次操作,以上堆已经变成了一个有序的数组,这就是堆排序。

void Heapify(int a[], int s,int m)
{
    int x = a[s];
    int j = 2 * s + 1;
    while(j < m)
    {
        if(j+1 < m && a[j] > a[j+1])
            j++;
        if(x < a[j])
            break;
        a[s] = a[j];
        s = j;
        j = j*2 + 1;
    }
    a[s] = x;
}
void BuildHeap(int a[], int n)
{
    for(int i = (n-1)/2; i >= 0; i--)
        Heapify(a, i, n);

}

void Heap_Sort(int a[], int n)
{
    BuildHeap(a, n);
    for(int i = n - 1; i > 0; i--)
    {
        a[0] += a[i];
        a[i] = a[0] - a[i];
        a[0] = a[0] - a[i];
        Heapify(a, 0, i);
    }
}


此外,求第k大(小)数,也经常使用堆来求解。


-------------------

End

阅读更多

没有更多推荐了,返回首页