堆排序HeapSort

 

堆排序,顧名思義,是採用數據結構堆來進行排序的一種排序算法。

研究沒有規律的堆,沒有任何意義。特殊的堆有最大堆(父節點值大於等於左右字節點值),最小堆(父節點值小於等於子節點值)。一般採用最大堆來進行排序,圖1爲最大堆來表示一維數組。

 

圖1 最大堆表示一維數組

 

2叉樹堆的幾點特性

1、 最後父節點索引值

不妨設堆的總元素個數爲N;最後一個父節點的索引值Index = N/2 ;可以寫幾個簡單的堆進行數學歸納。圖1中的最後一個父節點5 = 10 /2 ;

這個特性主要是在採用自底向上構建堆的時候,循環起始值。

 

2、父節點與子節點索引值關係

LeftIndex = parent * 2;

RightIndex = parent * 2 + 1;

 

對於任意一個節點K,其父節點爲K/2,其左子節點爲2K,右子節點爲2K+1。

Max-Heapify(保持最大堆屬性)

散亂排布的堆對算法的實現非常不友好,沒有意義。因此,在隨機數據輸入時,需要對數據按照最大堆的屬性進行一個初始排序。對一個父節點數據的max-heapify形象的推導直接採用算法導論的圖,如圖2。節點2的數據顯然不符合最大堆的數據定義(父節點值不小於子節點值),因此把MAX(parent,left,right)替換到父節點,父節點的數據替換 到子節點中。對於替換的子節點4,仍然需要判斷其是否滿足最大堆數據定義,一直遞歸到滿足定義。

 

圖2 max-heapify原理

 

構建最大堆

 

對所有的父節點都進行max-heapify操作,自底向上從最後父節點一直循環到根節點,很巧妙。採用自底向上能夠保證遍歷過的數據始終是保持最大堆屬性的,max-heapify操作始終是求當前父節點下所有子節點的最大值。

那自頂向下會怎樣呢?

 

第一次max-heapify後,根節點並沒有變成最大值,還要再遍歷下根節點,這個顯然在算法設計上不合適。所以自底向上的構思很巧妙。

 

HeapSort

 

首先保證輸出數據滿足最大堆的數據屬性(第一行),然後把最大值提取出來存儲在數組末端;然後計算剩下數據的最大堆,把最大值提出來;循環操作到排序完成。採用算法導論圖解

 

 

編程實現

 

 

void CHeapSort::maxHeapify( std::vector<int> &arrayA, int index )
{

    
    int l = leftChild(index);
    int r = rightChild(index);

    int maxValue = 0;

    if(l < heapSize && arrayA[l] > arrayA[index])
    {
        maxValue = l;
    }
    else
    {
        maxValue = index;
    }

    if(r < heapSize && arrayA[r] > arrayA[maxValue])
    {
        maxValue = r;
    }

    /* 父節點部位最大值 */
    if(maxValue != index)
    {
        std::swap(arrayA[index],arrayA[maxValue]);
        maxHeapify(arrayA,maxValue);
    }


}

void CHeapSort::buildMaxHeap( std::vector<int> &arrayA )
{
    heapSize = arrayA.size();
    int halfSize = heapSize >> 1;

    for(int i = halfSize ;i >= 0; i--)
    {
        maxHeapify(arrayA,i);
    }
}

void CHeapSort::heapSort( std::vector<int> &arrayA )
{
    buildMaxHeap(arrayA);

    for(int i = arrayA.size() - 1; i > 0; i--)
    {
        std::swap(arrayA[0],arrayA[i]);
        heapSize--;
        maxHeapify(arrayA,0);
    }
}

 

 結果:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章