import java.util.Arrays;
public class Main {
/**
* @param args
*/
//堆排序
//原理 先构建一个构建一个都是大根堆的完全二叉树
// 5
// 3 4
// 1 2
//一颗二叉树 父节点永远比两个子节点都大。这个叫做大根堆
//时间复杂度 O(N*logN)
//空间复杂度O(1)//
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {5,1,95,998,1,0,-5,-3,1,-5,8};
//脑补
//假装 arr数组是一个二叉树
//他的坐标 0是根节点 子节点分别是坐标值
//左:index*2+1 右 index*2+2
//父节点 为 子节点 坐标 (index-1)/2
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void heapSort(int[] arr){//不需要递归
if(arr==null||arr.length==1){
return;
}
for(int i=0;i<arr.length;i++){//构建一个大根堆
heapInsert(arr,i);
}
//遍历完刚好建立一个大根堆
int size = arr.length; //数组长度
swap(arr,0,--size);//把我们脑补的二叉树根节点 最一个孩子节点进行交换 --根节点一定是数组中最大的
//此时我们已经找到了数组中最大的值 那么下次行为将只会操作 N-1长度的数组
while(size>0){//重复一个过程找到所有的最大值并放到数组最后
heapify(arr, 0, size);
swap(arr,0,--size);
}
}
public static void heapInsert(int[] arr,int index){//
while(arr[index]>arr[(index-1)/2]){//如果这个节点比父节点小 (0-1)/2==0 如果index是0的话不会循环
swap(arr,index,(index-1)/2); //将比父节点小的值交换给父节点
index = (index-1)/2; //index =父节点 看看这个节点是不是比他的父节点要大
}
}
public static void heapify(int[] arr,int index,int size){
//大根堆二叉树的根节点 交换后大根堆已经被破坏
// 需要重新通过交换 来把二叉树变成大根堆
int left = index*2+1;//左孩子
while(left<size){
//left+1是右节点 首先应该判断一下右节点存在不存在
//然后 判断 左节点和右节点那个值大 largest = 下标
int largest = left+1<size &&arr[left+1]>arr[left]?left+1:left;
//判断比较大的那个子节点 是否大于他们的父节点
largest = arr[largest]>arr[index]?largest:index;
if(largest==index){
break;
//父节点大于最大的根节点
//终止 大根堆修复完成
}
//如果没有终止的话
//说明父节点小于根节点
//把他们位置交换 让大的数当父节点
swap(arr,largest,index);
//继续向下找
index=largest;
left = index*2+1;
}
}
public static void swap(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j]=temp;
}
}
堆排序(非递归版本)
最新推荐文章于 2022-03-27 15:17:59 发布