package Sort;
import java.util.Arrays;
public class heapsort {
private static int parentIdx(int childIdx) { //返回父节点下标
return (childIdx - 1) / 2; //索引从0开始, 注意childIdx=0时返回0
}
private static int leftChildIdx(int parentIdx) { //返回左孩子下标
return parentIdx*2 + 1;
}
//构建大顶堆
private static void buildMaxHeap(int[] datas)
{
int lastIdx = datas.length -1; //最后一个元素下标
for(int i=parentIdx(lastIdx); i>=0; i--) // 最外层循环; i初始为最后一个元素的父节点下标,通过控制i的大小来逐步向上构建大顶堆
{
int k = i; // 第一个父亲节点i暂存于k中
/*boolean isHeap = false;*/
while(/*!isHeap && */leftChildIdx(k) <= lastIdx) //获得较大孩子元素下标
{ //判断是否有孩子
int biggerChild = leftChildIdx(k);
if(biggerChild < lastIdx)
{ //有两个孩子
if(datas[biggerChild] <= datas[biggerChild+1])
//j+1 比较大, 选择大的
biggerChild++;//j总是保存较大子节点的索引
}
if(datas[k] > datas[biggerChild])
{ //父的比较大
/*isHeap = true;*/
break;
}
else
{
swap(datas, k, biggerChild); //较大孩子元素和父亲元素交换
k = biggerChild; //将biggerIndex(j)赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右孩子(因为父节点元素发生变化)
}
}
}
}
//保持大顶堆
private static void maintainMaxHeap(int[] datas, int lastIdx) {
int k = 0; //从根节点开始
while(k <= parentIdx(lastIdx)) { //终止条件为最后一个元素的父节点
int biggerChild = leftChildIdx(k);
if(biggerChild < lastIdx) { //有两个孩子
if(datas[biggerChild] <= datas[biggerChild+1]) { //j+1 比较大, 选择大的
biggerChild++;
}
}
if(datas[k] < datas[biggerChild]) { //父结点比较小
swap(datas, k, biggerChild);
k = biggerChild;
} else {
break; //跳出while循环体(所有子树都符合大根堆结构)
}
}
}
//排序过程
public static int[] sort(int[] datas) {
buildMaxHeap(datas); //由datas构建大顶堆
int lastIdx = datas.length - 1;//获取最后一个元素下标
while(lastIdx > 0) {
swap(datas, 0, lastIdx); //交换根元素和最后一个元素
lastIdx--;
if(lastIdx > 0) {
maintainMaxHeap(datas, lastIdx); //维持大顶堆(实际上是将最大的放到树根处)
}
}
return datas; //此时datas已由小到大排序完成
}
//交换数组中的两个元素
public static void swap(int [] a,int k,int j)
{
int tmp;
tmp=a[k];
a[k]=a[j];
a[j]=tmp;
}
public static void main(String[] args) {
int[] datas = {11,2,5,1,3,4,9,2,7,6,5};//{2, 9, 3, 7, 8, 6, 4, 5, 0, 1};
/*buildMaxHeap(datas);
System.out.println(Arrays.toString(datas));*/
sort(datas);
System.out.println(Arrays.toString(datas));
}
}