主要思想(升序):
將待排序序列構造成一個大頂堆,此時,堆頂就是該序列的最大值。將堆頂與末尾元素交換,此時末尾元素就是最大值。然後
將剩餘 n-1 個元素重新構造一個大頂堆,這樣得到n個元素的次小值。如此反覆執行,得到一個有序序列。
步驟:
1、創建大鼎堆;
從最後一個非葉子節點從下到上、從右到左調整堆
2、將堆鼎與堆尾交換
3、調整堆結構
比較堆頂與子節點,如堆頂小於子節點,交換;繼續比較交換後的節點與其子節點,重複執行,直到父節點大於子節點。
重複步驟2、3
package sortdemo;
import java.util.Arrays;
/**
* 堆排序demo
*/
public class HeapSort {
public static void main(String []args){
int []arr = {9,8,7,6,5,4,3,2,1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int []arr){
//1.構建大頂堆
for(int i=arr.length/2-1;i>=0;i--){
//從第一個非葉子結點從下至上,從右至左調整結構
adjustHeap(arr,i,arr.length);
}
//2.調整堆結構+交換堆頂元素與末尾元素
for(int j=arr.length-1;j>0;j--){
swap(arr,0,j);//將堆頂元素與末尾元素進行交換
adjustHeap(arr,0,j);//重新對堆進行調整
}
}
/**
* 調整大頂堆(僅是調整過程,建立在大頂堆已構建的基礎上)
* @param arr
* @param i
* @param length
*/
public static void adjustHeap(int []arr,int i,int length){
int temp = arr[i];//先取出當前元素i
for(int k=i*2+1;k<length;k=k*2+1){
//從i結點的左子結點開始,也就是2i+1處開始
if(k+1<length && arr[k]<arr[k+1]){
//如果左子結點小於右子結點,k指向右子結點
k++;
}
if(arr[k] >temp){
//如果子節點大於父節點,將子節點值賦給父節點(不用進行交換)
arr[i] = arr[k];
i = k;
}else{
break;
}
}
arr[i] = temp;//將temp值放到最終的位置
}
/**
* 交換元素
* @param arr
* @param a
* @param b
*/
public static void swap(int []arr,int a ,int b){
int temp=arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}