[编程题] 堆排序(数组与大顶堆的转换过程)
[编程题] 堆排序(数组与大顶堆的转换过程)
数组和树的关系
题目信息
如何把数组转换为二叉树呢?
思路
数组对应树的公式:
数组一个节点的左孩子: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};