堆排序算法步驟:
1、把無序數組構建成二叉堆。需要從小到大排序,則構建成最大堆;需要從大到小排序,則構建成最小堆。
2、循環刪除堆頂元素,替換到二叉堆的末尾,調整堆產生新的堆頂
複雜度
空間複雜度:因爲沒有開闢額外的集合空間,所以複雜度爲O(1)
時間複雜度 O(nlogn):
二叉堆的節點“下沉”是堆排序算法的基礎,這個複雜度是O(logn)
第1步,把無序數組構建成二叉堆,這一步的時間複雜度是O(n)
第2步,需要進行n-1次循環,每次循環調用一次下沉方法,所以第2步的計算規模是(n-1)*logn,所以整體的時間複雜度是O(nlogn)
和快排的區別
相同點:平均時間複雜度都是O(nlogn),都是步穩定排序
不同點:
1、快排的最壞時間複雜度是O(n2平方),堆排序的最壞時間複雜度是O(nlogn)
2、快排的評價空間複雜度O(logn),堆排序的空間複雜度是O(1)
public class HeapSoft {
public static void downAdjust(int[] arr,int parentIndex,int length){
int childIndex = parentIndex * 2 + 1;
//保存父節點的值,用於最後賦值
int temp = arr[parentIndex];
while (childIndex < length){
//如果又右孩子,且右孩子大於左孩子的值,則定位到右孩子
if(childIndex + 1 < length && arr[childIndex + 1] > arr[childIndex]){
childIndex ++ ;
}
//如果父節點大於任何一個孩子的值,則直接推出
if(temp >= arr[childIndex]){
break;
}
//無須真正交互,單向賦值即可
arr[parentIndex] = arr[childIndex];
parentIndex = childIndex;
childIndex = 2 * childIndex + 1 ;
}
arr[parentIndex] = temp;
}
public static void heapSort(int[] arr){
//把無序數組構建成最大堆
for(int i=(arr.length - 2)/2;i>=0;i--){
downAdjust(arr,i,arr.length);
}
System.out.println(Arrays.toString(arr));
for (int i=arr.length - 1;i>0;i--){
//最後一個元素和第一個元素進行交換
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
downAdjust(arr,0,i);
}
}
public static void main(String[] args) {
int[] arr = new int[]{1,3,2,6,5,7,8,9,10,0};
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
}