堆排序
標籤(空格分隔): 算法
堆實際上是一種滿二叉樹,所以我們可以直接利用父母節點與孩子節點之間在數組中的位置關係來操縱,而不需要真的建立一棵二叉樹。
堆分爲大頂堆(父節點比所有左右子孩子的排序碼都要大)和小頂堆(父節點比所有左右子孩子的排序碼都要小);
堆排序的過程分爲2個部分:
1. 根據輸入的初始數據,建立初始堆;
2. 通過一系列的元素交換和重新調整堆進行排序。
假設父節點在數組中的位置爲
代碼如下:
public class HeapSort {
/**
* 將最大的元素向下調整,生成大頂堆
* @param start
* @param end
* @param heap
*/
public static int[] siftDown(int start, int end, int[] heap) {
int i = start, j = i * 2 + 1;//令j指向左孩子
int temp = heap[i];
while(j <= end) {
if(j < end && heap[j] < heap[j+1])
j++; //令j指向較大的孩子
if(heap[i] >= heap[j])
break; //當前元素已是較大的元素
else {
heap[i] = heap[j];
i = j;
j = i * 2 + 1;
}
}
heap[i] = temp;
return heap;
}
/**
* 堆排序
* @param heap
*/
public static int[] heapSort(int[] heap) {
//建立初始堆,從第一個非葉節點開始調整
for(int i=(heap.length-2)/2; i>=0; i--) {
heap = siftDown(i, heap.length-1, heap);
}
//依次將大頂堆的對頂元素移動至最後,然後重新調整爲大頂推
for(int i=heap.length-1; i>0; i--) {
int temp = heap[0];
heap[0] = heap[i];
heap[i] = temp;
heap = siftDown(0, i-1, heap);
}
return heap;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = {5,3,7,1,10,4};
int[] res = heapSort(nums);
System.out.println(Arrays.toString(res));
}
}
算法複雜度爲:O(nlogn).