堆排序算法,基于選擇排序的思想,利用堆結構的性質來完成對數據的排序。
前提準備:
-
什么是堆結構:
堆數據結構是一種數組對象,它可以被視為一科完全二叉樹結構。它的特點是父結點的值大于(小于)兩個子結點的值(分別稱為大頂堆和小頂堆)
堆示意圖 堆結構的性質:
對于第n個結點而言 --- 它的父結點下標 i = (n-1)/ 2,左子結點 left = 2n+1,右子結點 right =2n+2
結構圖
算法基本思想:
1. 構建堆(大頂堆或小頂堆,現以大頂堆為例):
- 首先從最后一個結點開始,找到它的父結點,在父結點和父結點的左右結點中,選出最大的值,與父節點交換。
- 然后對倒數第二個結點執行同樣的操作
- 這樣直到根結點的時候,根結點變成了所以數據中最大的值。
2. 替換根結點,重建堆:
- 將根結點與最后一個結點的數據交換,在把倒數第二個結點視為最后一個結點,重新建堆。
- 重復上述的操作。最終,數據排序完成。
代碼實現:
import java.util.Arrays;
/**
* Created by noonbiteun
* Date: 2017/7/31
*/
public class HeapSort {
//建堆
private static void heapConstruct(int[] arr, int last) {
int tmp;
for (int parent = (last - 1) / 2; parent >= 0; parent = (last-1) / 2) {
if (2*parent+1 < last) {
//第last個節點為右子樹
if (arr[last - 1] < arr[last]) {
//大的數據往前移
tmp = arr[last];
arr[last] = arr[last - 1];
arr[last - 1] = tmp;
} else {
last--;
}
}
if (arr[parent] < arr[last]) {
//大的數據移到父節點
tmp = arr[last];
arr[last] = arr[parent];
arr[parent] = tmp;
}
last--;
}
}
private static void sort(int[] arr) {
int last = arr.length - 1;
int tmp;
System.out.println("原始順序: " + Arrays.toString(arr));
for (int i = 0; i < arr.length; i++) {
heapConstruct(arr, last);
//第一個和最后一個交換
tmp = arr[0];
arr[0] = arr[last];
arr[last] = tmp;
last--;
System.out.println("第" + i + "趟排序:" + Arrays.toString(arr));
}
}
public static void main(String[] args) {
int[] arr = new int[10];
//初始化數組
for (int i = 0; i < 10; i++) {
arr[i] = (int) (Math.random() * (100 + 1));
}
HeapSort.sort(arr);
}
}
輸出結果:
運行結果
小結分析:
經過兩三天的不斷學習,感覺這方面在一點點的進步,今天的這個堆排序,只看了書上寫的算法思想之后,馬上就能寫出來,感覺比前幾天對著一個冒泡排序死磕了一個小時要進步很大了,加油。