完全二叉樹(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。詳細過程如下圖所示:
根據前面對堆排序的介紹,有如下**。
在堆排序過程中每輪交換根結點和最後乙個結點後的二叉樹上,以根結點的子結點為根結點的子樹就是乙個大頂堆(在堆排序示意圖中,第一輪交換後,以根節點4的兩個子節點21、32為根節點的子樹依然是大頂堆)。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;}}
在上邊**中,每輪構造大頂堆時,都是以樹上最後乙個非葉子結點開始遍歷,而樹上除根結點外的非葉子結點所構成的樹已經是大頂堆,這就造成了沒有必要的遍歷,增加了迴圈的次數。
我們可以調整**邏輯為:首先通過遍歷所有的非葉子結點去構造乙個大頂堆,然後在以後調整大頂堆過程中都是從根節點開始。
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 的幾種常見排序方法。最小堆的講解以及最小堆元素的插入和刪除參見最小堆操作。以下繼續引用以...