堆排序的時間復雜度分析


本文包括堆排序的代碼例子(圖示)時間復雜度分析 

 

#define MAXSIZE 10000

/*全局變量,需要排序的數組*/
long long int num[MAXSIZE];

/*對非葉子結點和它的孩子結點進行調整,使其重新成為大根堆,用於堆排序*/
void NodeSort(long long int node,long long int len)
{
    long long int left = node * 2 + 1, right = left + 1, max_node = left;
    while (left < len)
    {
        if (right < len && num[left] < num[right])            
                max_node = right;
        if (num[node] < num[max_node])
        {
            swap(node, max_node);
            node = max_node;
            left = node * 2 + 1;
            right = left + 1;
            max_node = left;
        }
        else
            return;
    }
}

/*堆排序*/
void HeapSort(long long int len)
{
    while (len != 0)
    {
        for (long long int i = len; i > 0; i -= 2)//將非葉子結點依次進行調整,保證每次for循環結束之后都是大根堆
            NodeSort((i - 1) / 2, len);
        swap(len - 1, 0); //首尾元素交換       
        len--;//對除了最后一個元素外的數組繼續進行排序
    }
}

 

 

例子圖示:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 之后按照上述的調整堆的方式,不斷進行調整,直到堆只剩下根節點的時候,數組有序

 

下面的一些計算可以代入上面的例子理解

 

堆排序分為兩步,即初始化堆、調整堆。

 

兩個步驟都要調用一個調整結點順序的函數NodeSort,以大根堆為例,操作為:

1:如果父親結點num[a]和它的兩個孩子結點num[2a+1], num[2a+2]滿足um[a] > max{num[2a+1], num[2a+2]},那么返回;

2:如果不滿足堆的性質,那么將父親結點num[a]和較大孩子結點max{num[2a+1], num[2a+2]}交換,

3:將原來較大的孩子結點作為父親結點,重復上述操作,直到孩子結點是葉子結點為止

 

初始化堆的時間復雜度分析

初始化堆的時候,對於每個非葉子結點,都要調用上述函數,將它與它的孩子結點進行比較和交換,順序是從后向前。

以操作2作為基本操作,對每一層都完全鋪滿的堆進行分析,

設元素個數為n,則堆的高度k=log(n+1)≈log n,非葉子結點的個數為2^(k-1)-1

假設每個非葉子結點都需要進行調整,則第i層的非葉子結點需要的操作次數為k-i,

第i層共有2^(i-1)個結點,則第i層的所有結點所做的操作為k*2^(i-1)- i*2^(i-1),

共k-1層非葉子結點,總的操作次數為 

    

 

化簡可得,上式=2^k-k+1,將k=log(n+1)≈log n代入,得n - log n +1,

所以,初始化堆的復雜度為O(n)

 

調整堆的時間復雜度分析

調整堆的復雜度計算和初始化堆差不多,

假設根節點和排在最后的序號為m的葉子結點交換,並進行調整,那么調整的操作次數 = 原來m結點所在的層數 = 堆的高度(因為m結點在堆的最后)= log m

共n個結點,調整的總操作次數為

     

 

化簡可得,上式=log (n-1)! ≈ n*log n

 所以,調整堆的復雜度為O(n*log n)

 

所以,總體復雜度為O(n*log n)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM