读书日记- 堆排序算法

堆排序

  不仅在排序上有较好的时间复杂度,同时最大堆,最小堆在解决top10等问题上有很好的效果。

最大堆性质,除了根以为的所有结点i都要满足:

  A[parent(i)]>=A[i]

即,子节点一定小于等于父节点,且任意子树也满足该性质。

Max-Heapify是维持最大堆性质的关键。时间复杂度O(lgn).

#define LEFT(a)  ((a)*2+1)
#define RIGHT(a)  ((a)*2+2)
void ExChange(int& a,int& b)
{
     a=a^b;  
     b=a^b;  
     a=a^b;
}
void Max_Heapify(int* intArr,int i,int length)
{      
    int l = LEFT(i);
    int r = RIGHT(i);

    int largest = i;
    if (l< length && intArr[l] >intArr[largest])
    {
        largest = l;
    }
    if (r< length && intArr[r] >intArr[largest])
    {
        largest = r;
    }

    if(largest!=i)
    {
        ExChange(intArr[i],intArr[largest]); 
        Max_Heapify(intArr,largest,length);
    }
}

通过Max_Heapify可以使root不符合性质递归保持最大堆的性质。

如下:

                    16

       4              10

        14       7       9       3

        2     8   1

        (a)

                     16

      14              10

         4        7     9       3

        2     8   1

        (b)

                  16

     14          10

        8     7       9    3

        2     4    1

        (c)

建堆:

  通过自底向上的方法调用Max_Heapify,即可把一个数组转换为最大堆。

  

void Build_Max_Heap(int* intArr,int length)
{
    for(int i=length/2+1;i>=0;i--)
    {
        Max_Heapify(intArr, i,length);
    }
}

排序:

    在有了一个最大堆后,通过不断取出最大值,并对剩余的值进行Max_Heapify即可保持最大堆性质,始终从根节点取得当前最大值,从而实现排序。

代码如下:

void Heap_Sort(int* intArr,int length)
{
    Build_Max_Heap(intArr,length);
    for(int i= length-1;i>0;i--)
    {
        ExChange(intArr[0],intArr[i]);
        Max_Heapify(intArr,0,--length);
    }
}

 

因为每次Max_Heapify时间为O(logn),所以堆排序时间为O(nlogn)

原文地址:https://www.cnblogs.com/stratrail/p/5040472.html