package com.zhao.algorithm.sort;
import java.util.Arrays;
/**
* AUTHOR :zhao
* 日期:2020/2/15 18:51
* 堆排序 堆排序是将数据看成是完全二叉树、根据完全二叉树的特性来进行排序的一种算法
* 排序过程:
* 1.构造一个大顶堆,取堆顶数字,也就是最大值
* 2.再将剩下的数字构建一个大顶堆,取堆顶数字,也就是剩下值当中的最大值
* 3.重复以上操作,直到取完堆中的数字,最后得到一个从大到小排列的序列
*/
public class HeapSort {
public static void main(String[] args) {
int[] array={9,6,8,7,0,1,10,4,2,78,65};
headSort(array);
System.out.println(Arrays.toString(array));
}
/**
* 堆是通过一维数组来实现的。在起始数组为 0 的情形中:
* 父节点 i 的左子节点在位置 (2*i+1);
* 父节点 i 的右子节点在位置 (2*i+2);
* 子节点 i 的父节点在位置 (i-1) / 2;
*/
/**
* 堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。
*/
static void headSort(int[]arr){
/**
* 调整该数组为一个大顶堆数组
* 开始位置是一个非叶子结点, 即最后一个节点的父节点
*/
for (int i = (arr.length-1)/2; i >=0 ; i--) {
maxHeap(arr,arr.length,i);
}
//排序,不断交换堆中的最大值到数组的后面去,因为d在不断缩小,获取最大堆时替换的这个值不会被考虑进去 eg: leftNode<size
for (int d = arr.length-1; d >0 ; d--) {
int t = arr[0];
arr[0] = arr[d];
arr[d]=t;
maxHeap(arr,d,0);
}
}
/**
* 可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树
* 完全二叉树: 除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐。
* 满二叉树:除了叶子结点之外的每一个结点都有两个孩子,每一层(当然包含最后一层)都被完全填充。
* 完满二叉树:除了叶子结点之外的每一个结点都有两个孩子结点。
* 完全二叉树有个特性:左边子节点位置 = 当前父节点的两倍 + 1,右边子节点位置 = 当前父节点的两倍 + 2
* 构建最大堆
* @param arr 数组
* @param size 数字长度
* @param index 从哪里开始建堆
*/
static void maxHeap(int[]arr ,int size,int index){
//左节点
int leftNode=index*2+1;
//右节点
int rightNode=index*2+2;
//最大值 索引
int max=index;
//比较左节点
if(leftNode<size&&arr[max]<arr[leftNode])
max=leftNode;
//比较右节点
if(rightNode<size&&arr[max]<arr[rightNode])
max=rightNode;
//如果右最大值交换,并递归交换后的节点
if(index!=max){
int temp=arr[index];
arr[index]=arr[max];
arr[max]=temp;
// 递归交换后的节点
maxHeap(arr, size, max);
}
}
}