排序演算法之堆排序

2021-08-15 05:58:23 字數 2419 閱讀 4790

完全二叉樹(complete binary tree):若設二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊,這就是完全二叉樹。

堆總是滿足以下兩個特性:

其中,每個結點的值總是不大於其子結點的值,這種堆成為小根堆

每個結點的值總是不小於其子結點的值,這種堆稱為大根堆

因此,對於乙個大根堆r來說,元素r[i](i為元素位置,從0開始)有:

根據堆的性質可知:根結點是最大(或最小)的結點。

因此,對於乙個待排序陣列可以對陣列構造出乙個大頂堆,然後將去除最大值的陣列再次構造大頂堆,直到待排序序列剩下乙個元素為止,每次拿出的數即構成了乙個有序序列。

根據上述,排序過程可總結為如下兩個操作:

將陣列構造成乙個大頂堆。

交換第乙個(堆的根節點)和最後乙個元素(堆上最後一層最右的葉子結點)即把大的元素放到陣列最後。然後在將去除最後乙個元素的陣列重新構造大頂堆。

重複上面兩個操作,直到堆中只剩下乙個結點。

在乙個完全二叉樹上,對於任意結點r[i],對以r[i]為根結點的樹(假設以r[i]的子結點為根節點的樹即r[i]的左子樹和右子樹已經是大頂堆)進行以下操作:

取r[i]的子結點中較大的結點r[2*i+1](此處假設左結點大於右結點)。

若r[2*i+1]不大於r[i],則結束。否則,交換r[i]和r[2*i+1],交換完成後,以r[2*i+1]為根結點,重複上述步驟。

結束後,以r[i]為根結點的樹即為乙個大頂堆。

對陣列[3, 4, 63, 4, 0, 1, 32, -2, 21]構造大頂堆過程如下圖所示:

構造大頂堆一般先從樹上最後乙個非葉子節點開始(上圖中深度為3、值為4的節點),然後逐漸遍歷樹上非葉子節點,直到根節點。也就是說對乙個元素個數為 n 的(陣列長度為n)的樹而言,非葉子節點遍歷順序為: (n-2)/2, ((n-2)/2)-1、((n-2)/2)-2、… 、2、1、0。

詳細過程如下圖所示:

根據前面對堆排序的介紹,有如下**。

public

int sort(int array)

return array;

}private

void

initheap(int array, int length)

// 如果大結點小於父結點直接結束

if (array[maxchild] <= parentvalue)

// 將大結點的值賦值給父結點

array[parent] = array[maxchild];

// 發生交換後,繼續調整已大結點為根結點的樹

parent = maxchild;

maxchild = 2 * parent + 1;

}array[parent] = parentvalue;}}

在堆排序過程中每輪交換根結點和最後乙個結點後的二叉樹上,以根結點的子結點為根結點的子樹就是乙個大頂堆(在堆排序示意圖中,第一輪交換後,以根節點4的兩個子節點21、32為根節點的子樹依然是大頂堆)。

在上邊**中,每輪構造大頂堆時,都是以樹上最後乙個非葉子結點開始遍歷,而樹上除根結點外的非葉子結點所構成的樹已經是大頂堆,這就造成了沒有必要的遍歷,增加了迴圈的次數。

我們可以調整**邏輯為:首先通過遍歷所有的非葉子結點去構造乙個大頂堆,然後在以後調整大頂堆過程中都是從根節點開始。

private

static

void

adjustheat(int array, int parent, int length)

// 如果大結點小於父結點直接結束

if (array[maxchild] <= parentvalue)

// 將大結點的值賦值給父結點

array[parent] = array[maxchild];

// 發生交換後,繼續調整以大結點為根結點的樹

parent = maxchild;

maxchild = 2 * parent + 1;

}array[parent] = parentvalue;

}public

void

sort(int array)

// 進行n-1次迴圈,完成排序

for (int length = array.length - 1; length > 0; length--)

}

排序演算法之堆排序

前言 今天我來介紹下堆排序,在寫堆排序 之前,我們要知道堆的概念!堆的定義 n個關鍵字序列kl,k2,kn稱為 heap 當且僅當該序列滿足如下性質 簡稱為堆性質 1 ki k 2i 且ki k 2i 1 1 i n 當然,這是小根堆,大根堆則換成 號。k i 相當於二叉樹的非葉子結點,k 2i 則...

排序演算法之堆排序

堆排序演算法是選擇排序的一種,該演算法只是通過堆,最大堆 或者最小堆選擇出乙個待排序序列中的最大值,或者最小值。要想實現堆排序演算法,就需要構建什麼堆,這裡也最小堆為例。說明什麼是堆,怎麼構建乙個堆。假設待排序序列為a n 為乙個陣列。陣列的長度為n 陣列下標為 0,1,2,i,2i,2i 1 n ...

排序演算法之堆排序

宣告 本博文 為樓主親自編寫並測試,其它內容引用至我一直很崇拜的牛人morewindows。他對排序演算法的講解通俗易懂,給人一種耳目一新的感覺。堆排序與快速排序 歸併排序 一樣都是時間複雜度為o n logn 的幾種常見排序方法。最小堆的講解以及最小堆元素的插入和刪除參見最小堆操作。以下繼續引用以...