此代码是针对于大顶堆实现的,小顶堆的修改方式,在代码注释中,看代码前,需对数组的顺序储存二叉树,大顶堆小顶堆的知识有足够的了解,废话不多说,上代码
//堆排序
public static void heapSort(int[] array){
//先将数组构建成一个大顶堆,对于一个数组来说,其顺序储存二叉树的最后一个父节点的位置(下标index)就是length/2-1
//从最后一个父节点开始,依次把每一层的父节点都实现成大顶堆
for (int i = array.length/2-1; i >=0; i--) {
adjustBigHeap(array,i, array.length);
}
//大顶堆目的,将数组中的最大值推到堆顶
//大顶堆化完成后,此时堆顶的节点即array[0]为该数组的最大值
//大顶堆化的特点,每一层的节点值,都是该节点构成子树中所有节点的最大值,即每一层的值都比下面层的值大
//利用大顶堆将数组排序
int temp;//交换媒介
for (int i = array.length-1; i>=0 ; i--) {
//由于数组已经大顶堆化,此时只需将array[0]与数组最后一个交换,即数组最大值排到组尾
temp = array[0];
array[0] = array[i];
array[i] = temp;
//交换后,数组长度减一,由于堆顶(array[0])元素值发生改变,需从堆顶开始重新大顶堆化
adjustBigHeap(array,0,i);
}
}
private static void adjustBigHeap(int[] array,int start,int length){
int temp = array[start];//将遍历起点的父节点值保存
for (int i = (start<<1)+1; i < length; i = (i<<1)+1) {//目的:找出该父节点下的较大子节点,并将其子节点与父节点比较交换
//比较子节点的大小,此刻i为左子节点的index
//下面两个if判断是决定大顶堆化还是小顶堆化的关键
if(i+1<length&&array[i]<array[i+1]){//目的:筛选出子节点中较大的节点
//若左子节点值小于右子节点,则将父节点的比较目标移至右子节点
i++;
}
if(array[i]>temp){//目的:将父节点与子节点中较大的节点比较交换
//子节点大于父节点,满足交换条件
array[start] = array[i];
//交换完成后,由于子节点的值发生了变化,则该子节点下的子树可能已不满足大顶堆
//需将该子节点记录为父节点,进行该子节点下的大顶堆化
start = i;
}
else {//如果没有和子节点发生交换,说明此时该父节点(temp值)已是大顶堆结构,则跳出循环,此父节点的的大顶堆化完成
break;
}
}
//将temp值赋给最后跳出循环的该父节点
array[start] = temp;
}