最容易理解的堆排序升級版——Java實現
阿新 • • 發佈:2020-12-25
需求分析:要求將給定的無序陣列有序化
思路:迴圈刪除堆頂元素,直到堆空,將堆頂元素記錄到結果陣列中
remove函式:刪除並返回堆頂元素(用array[lastIndex]覆蓋array[0],再將array[lastIndex]賦值為0,並下濾array[0]).
方法:
static int lastIndex;
public static int[] heapSort2(int[] array){
int[] result = new int[array.length];
int cnt = array. length;
int j = 0;
heapify(array); //批量建堆
lastIndex = array.length-1;
while(cnt-- > 0){
result[j++] = remove(array);
}
return result;
}
public static void siftDown(int index, int[] array) {
int element = array[index];
int half = array.length >> 1;
// 第一個葉子節點的索引 == 非葉子節點的數量
// index < 第一個葉子節點的索引
// 必須保證index位置是非葉子節點
while (index < half) {
// index的節點有2種情況
// 1.只有左子節點
// 2.同時有左右子節點
// 預設為左子節點跟它進行比較
int childIndex = (index << 1) + 1;
int child = array[childIndex];
// 右子節點
int rightIndex = childIndex + 1;
// 選出左右子節點最大的那個
if (rightIndex < array.length && array[rightIndex] > child) {
child = array[childIndex = rightIndex];
}
if (element >= child) break;
// 將子節點存放到index位置
array[index] = child;
// 重新設定index
index = childIndex;
}
array[index] = element;
}
/**
* 批量建堆
* @param array
* @param
*/
//自下而上的下濾
public static void heapify(int[] array){
for (int i = (array.length >>1) - 1; i >= 0; i--){
siftDown(i,array);
}
}
/*
刪除堆頂元素,並返回
*/
public static int remove(int[] array){
emptyCheck(array);
int rtn = array[0];
array[0] = array[lastIndex];
array[lastIndex] = 0;
lastIndex--;
siftDown(0,array);
return rtn;
}
public static void emptyCheck(int[] array){
if (array.length == 0){
throw new IndexOutOfBoundsException("Heap is empty");
}
}
主函式:
public static void main(String[] args){
int[] arr = {1,3,5,2,4,7,8};
System.out.println(Arrays.toString(heapSort2(arr)));
}
執行結果: