堆排序的介紹
堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分爲大根堆和小根堆,是完全二叉樹。
- 完全二叉樹:除了最後一層之外的其他每一層都被完全填充,每一層從左到右的填充數據,不能空缺
- 大根堆:任意一個節點的值均大於等於它的左右孩子的值,位於堆頂的節點值最大
- 小根堆:任意一個節點的值均小於等於它的左右孩子的值,位於堆頂的節點值最小
本節分享的堆排序以大根堆爲例子,大根堆的圖示
講解鋪墊(及其重要)
實際上要排序的是一個數組 int[] arr={3, 4, 5, 6, 7, 0, 2, 9, 8},上面的堆是我們幻想出來的,然後知道了arr數組的下標 i 後,我們可以得出它的父節點是**(i-1)/ 2**,它的左孩子是2*i+1,它的右孩子是2*i+2。
堆排序的實現步驟
-
把一個數組調整爲大根堆(heapInsert)
假設當前節點的下標爲i,那麼它的父親節點爲(i-1)/2,每次heapInsert的時候就把insert進來的節點與它的父親節點進行比較,比它的父節點大就交換,一直重複調整 -
每次把堆頂放到最後的節點位置,然後調整整個堆爲大根堆(heapify)
每次把堆頂的節點放到最後,然後堆大小減1,然後調整爲大根堆,一直重複,直到大根堆的大小爲0爲止
代碼實現
import java.util.Arrays;
/**
* @author god-jiang
* @date 2020/1/10
*/
public class HeapSort {
//heapInsert就是建立大根堆
public static void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
//heapify就是把堆頂和最後一個數交換位置,然後堆的大小size--
public static void heapify(int[] arr, int index, int size) {
int left = 2 * index + 1;
while (left < size) {
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
largest = arr[index] > arr[largest] ? index : largest;
if (largest == index)
break;
swap(arr, index, largest);
index = largest;
left = 2 * index + 1;
}
}
//交換兩個數
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//主函數
public static void main(String[] args) {
int[] arr = {3, 4, 5, 6, 7, 0, 1, 2, 9, 8};
int size = arr.length;
for (int i = 0; i < size; i++) {
heapInsert(arr, i);
}
swap(arr, 0, --size);
while (size > 0) {
heapify(arr, 0, size);
swap(arr, 0, --size);
}
System.out.println(Arrays.toString(arr));
}
}
運行截圖
總結
堆排序是排序算法裏面比較經典的一個算法吧,它的時間複雜度爲O(NlogN)。建立堆的時間複雜度爲O(N),然後堆的調整每步都是O(logN),所以進行了heapify之後就是O(NlogN)。以上就是我對堆排序的整個過程的理解。
PS:覺得博主寫的不錯的點點贊,關注走一波,謝謝大家的支持了