1. 堆原理
1.父結點的鍵值總是大於或等於(小於或等於)任何一個子節點的鍵值。
2.每個結點的左子樹和右子樹都是一個二叉堆(都是最大堆或最小堆)。
當父結點的鍵值總是大於或等於任何一個子節點的鍵值時爲最大堆。當父結點的鍵值總是小於或等於任何一個子節點的鍵值時爲最小堆。
可以看出,其實堆排序的數據都是存儲在數組中的,只是我們操作的時候把它用作完全二叉樹進行排序。
3 . 堆的存儲
一般都用數組來表示堆,i結點的父結點下標就爲(i – 1) / 2。它的左右子結點下標分別爲2 * i + 1和2 * i + 2。如第0個結點左右子結點下標分別爲1和2。
4 . 堆操作-插入刪除
2. 排序原理
由於堆也是用數組模擬的,故堆化數組後,第一次將A[0]與A[n - 1]交換,再對A[0…n-2]重新恢復堆。第二次將A[0]與A[n – 2]交換,再對A[0…n - 3]重新恢復堆,重複這樣的操作直到A[0]與A[1]交換。由於每次都是將最小的數據併入到後面的有序區間,故操作完成後整個數組就有序了。
大根堆排序算法的基本操作
① 初始化操作:將A[0..n]構造爲初始堆;
②每一趟排序的基本操作:將當前無序區的堆頂記錄R[0]和該區間的最後一個記錄交換,然後將新的無序區調整爲堆(亦稱重建堆,其實重建堆的操作也就是建立堆操作)。
3. java實現堆排序代碼
public class HeapSort {
public static void main(String[] args) {
int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3 };
System.out.println("Before heap:");
ArrayUtils.printArray(array);
heapSort(array);
System.out.println("After heap sort:");
ArrayUtils.printArray(array);
}
public static void heapSort(int[] array) {
if (array == null || array.length <= 1) {
return;
}
buildMaxHeap(array);
for (int i = array.length - 1; i >= 1; i--) {
ArrayUtils.exchangeElements(array, 0, i);
maxHeap(array, i, 0);
}
}
private static void buildMaxHeap(int[] array) {
if (array == null || array.length <= 1) {
return;
}
int half = array.length / 2;
for (int i = half; i >= 0; i--) {
maxHeap(array, array.length, i);
}
}
private static void maxHeap(int[] array, int heapSize, int index) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int largest = index;
if (left < heapSize && array[left] > array[index]) {
largest = left;
}
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
if (index != largest) {
ArrayUtils.exchangeElements(array, index, largest);
maxHeap(array, heapSize, largest);
}
}
}