[編程題] 堆排序(數組與大頂堆的轉換過程)
數組和樹的關系
題目信息
如何把數組轉換為二叉樹呢?
思路
數組對應樹的公式:
數組一個節點的左孩子:2*i+1
數組一個節點的右孩子:2*i+2
某節點的父親節點:(i-1)/2
注意
數組轉為大頂堆
思路
思路:在每一個節點進入的時候,就會比較其與父節點的大小關系,調整樹結構。(這里即是交換數組中的元素),建立出了大頂堆的數組。
建立大頂堆的時間復雜度
時間復雜度:O(nlogn)
Java代碼
package Demo11_堆;
import java.lang.reflect.Parameter;
import java.util.Arrays;
/**
* @author jiyongjia
* @create 2020/8/9 - 13:23
* @descp:
*/
public class P3_堆排序 {
public static void main(String[] args) {
int[] arr = {10, 131,3,42,221,3,2,-1,0,-32, 40, 5, 2, 18};
// heapify(arr,arr.length,0);
// heap_build(arr);
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 1 heapify操作(需要按照傳入的i的父節點進行遞歸的heapify操作)
* @param arr 數組
* @param n 數組的個數
* @param i 傳入的父節點的索引號(如0)
*/
public static void heapify(int[] arr,int n,int i){
//遞歸的出口
if(i>=n){return;}
int l = 2*i+1;
int r = 2*i+2;
int maxIndex = i;
if(l<n && arr[l]>arr[maxIndex]){ //TODO:注意
maxIndex = l;
}
if(r<n && arr[r]>arr[maxIndex]){
maxIndex = r;
}
if(maxIndex != i){
swap(arr,i,maxIndex);//只有不等才交換
//遞歸處理
heapify(arr,n,maxIndex);
}
}
public static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
*2 使用heapify從最后一個非葉子節點往前遍歷每個父節點,然后生成一個大頂堆
* @param arr
*/
public static void heap_build(int[] arr){
int n = arr.length;
int lastNodeParent = (n-1-1)/2; //根據公式計算最后一個非葉子節點(即最后一個父節點)
for (int i = lastNodeParent; i >=0 ; i--) {
heapify(arr,arr.length,i); //倒着推的從下往上構建好堆
}
}
//3 構建好堆之后,每次把堆頂的元素和最后一個元素交換,得到一個最大值放最后了
public static void heapSort(int[] arr){
heap_build(arr);//先構造出一個堆
for(int i=arr.length-1;i>=0;i--){
//經過交換,最大的堆頂到了最后一個元素的地方
swap(arr,i,0);
//下次heapfify就不考慮這個最后的這個堆即可
heapify(arr,i,0); //從0開始heapify這個堆來調整堆。此次最大值已經在最后位置了,所以這里傳的數組長度為i
}
}
}
輸出:
int[] arr = {10, 131,3,42,221,3,2,-1,0,-32, 40, 5, 2, 18};