夯實基礎:排序演算法之堆排序
概念
堆排序(英語:Heapsort)是指利用堆這種資料結構所設計的一種排序演算法。堆是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。--《百度百科》
堆是什麼?
堆是一個可以被看做一棵樹的陣列物件。
堆有兩種:
每個節點的值都大於或等於其子節點的值,的大頂堆。大頂堆適用於從小到大的排序。
每個節點的值都小於或等於其子節點的值,的小頂堆。小頂堆適用於從大到小的排序。
模擬堆排序過程
任務:使用堆排序將陣列從大到小排列。
原始陣列:
以堆的圖形結構顯示:
我們從後向前,先把小與父節點的最小節點與父節點交換過程如下:
1.先從節點10開始,因為他的子節點是陣列的最後值。
8沒有兄弟節點,且8 < 10,所以8與10交換。
2.我們再來到節點12,節點12有兩個子節點3與5,先比較兩個子節點的大小:3 < 5,所以3再與12比較,3 < 12,所以3與12交換。
3.來到節點4,節點4有兩個子節點6與15,先比較兩個子節點的大小:6 < 15,所以6再與4比較:4 < 6,所以節點4不需要交換。
4.來到節點11,節點11有兩個節點3與8,先比較兩個子節點的大小:3 < 8,所以3再與11比較:3 < 11,所以3與11交換。
然後交換後的節點11還有兩個子節點5與12,先比較兩個子節點的大小:5 < 12,所以5再與11比較:5 < 11,所以5與11交換。
5.來到節點17,節點17有兩個節點3與4,先比較兩個子節點的大小:3 < 4,所以3再與17比較:3 < 17,所以3與17交換。
交換後的節點17有兩個子節點5與8,先比較兩個子節點的大小:5 < 8,所以5再與17比較:5 < 17,所以5與17交換。
再次交換後的節點17有兩個節點11與12,先比較兩個子節點的大小:11 < 12,所以11再與17比較:11 < 17,所以11與17交換。
這樣,我們就完成了一個小頂堆。
獲取到了陣列最小值3,然後3與10交換,刨除3再次完成小頂堆。
重複上面的步驟直到小頂堆長度為1。
堆排序程式碼
public static void minHeapDown(int[] array, int start, int end) {
int current = start; // 當前(current)節點的位置
int left = 2 * current + 1; // 左(left)孩子的位置
int tmp = array[current]; // 當前(current)節點的大小
for (; left <= end; current = left, left = 2 * left + 1) {
// "left"是左孩子,"left+1"是右孩子
if (left < end && array[left] > array[left + 1])
left++; // 左右兩孩子中選擇較小者
if (tmp <= array[left])
break; // 調整結束
else { // 交換值
array[current] = array[left];
array[left] = tmp;
}
}
}
public static void HeapSort(int[] array) {
int start, tmp;
int length = array.length;
for (start = length / 2 - 1; start >= 0; start--)
minHeapDown(array, start, length - 1);
// 從最後一個元素開始對序列進行調整,不斷的縮小調整的範圍直到第一個元素
for (start = length - 1; start > 0; start--) {
// 交換array[0]和array[i]。交換後,array[i]是array[0...i]中最小的。
tmp = array[0];
array[0] = array[start];
array[start] = tmp;
// 調整array[0...i-1],使得array[0...i-1]仍然是一個最小堆。
// 即,保證array[i-1]是array[0...i-1]中的最小值。
minHeapDown(array, 0, start - 1);
}
}
堆排序效率
時間複雜度:堆排序的時間複雜度跟歸併排序是一樣的,都是N個元素迴圈logN次,所以時間複雜度為O(N * logN)。
空間複雜度:O(1)。
穩定性:不穩定。因為堆排序是根據父節點選擇比較進而交換排序,與父節點大小關係的不確定性,進而出現A1大於父節點不發生交換,A2小於父節點發生交換操作,造成A2排到了A1前面。所以堆排序是不穩定的。
相關文章
- 排序演算法-堆排序排序演算法
- 排序演算法__堆排序排序演算法
- 排序演算法 - 堆排序排序演算法
- 演算法學習之選擇排序和堆排序:演算法排序
- 基礎演算法之排序演算法演算法排序
- 基礎夯實:基礎資料結構與演算法(一)資料結構演算法
- 常見演算法 PHP 實現 -- 堆排序演算法PHP排序
- C#堆排序演算法C#排序演算法
- 圖解堆排序演算法圖解排序演算法
- Python 一網打盡<排序演算法>之堆排序演算法中的樹Python排序演算法
- 演算法與資料結構之原地堆排序演算法資料結構排序
- PHP基礎演算法之快速排序法PHP演算法排序
- JavaScript夯實基礎系列(三):thisJavaScript
- js 實現堆排序JS排序
- 老生常談之 PHP 基礎排序演算法PHP排序演算法
- 基礎演算法系列 之希爾排序演算法排序
- PHP基礎演算法之選擇排序法PHP演算法排序
- PHP基礎演算法之氣泡排序法PHP演算法排序
- 看懂堆排序——堆與堆排序(三)排序
- 基礎夯實:作業系統作業系統
- JavaScript夯實基礎系列(四):原型JavaScript原型
- JavaScript夯實基礎系列(五):類JavaScript
- 排序演算法:堆排序的實現和時間複雜度分析排序演算法時間複雜度
- 堆排序排序
- 堆排序(實現c++)排序C++
- 堆排序c++實現排序C++
- 使用 Swift 實現堆排序Swift排序
- 演算法基礎:排序演算法:選擇排序演算法排序
- Python八大演算法的實現,插入排序、希爾排序、氣泡排序、快速排序、直接選擇排序、堆排序、歸併排序、基數排序。Python演算法排序
- JavaScript夯實基礎系列(二):閉包JavaScript
- js堆排序JS排序
- python 堆排序Python排序
- 資料結構和演算法面試題系列—排序演算法之基礎排序資料結構演算法面試題排序
- 【資料結構與演算法】堆排序資料結構演算法排序
- 資料結構與演算法——堆排序資料結構演算法排序
- 資料結構與演算法:堆排序資料結構演算法排序
- 【譯】Swift演算法俱樂部-堆排序Swift演算法排序
- 【轉】堆排序Heap Sort——Java實現排序Java