/*********************
* 堆排序
* 堆排序本质是将数组视为完全二叉树进行操作
* 如果是进行升序排序,那么需要将堆初始化为大根堆(所有的节点的值均大于左右孩子节点的值)
* 反之,初始化为小根堆
* 堆排序主要分为两个过程:将数组初始化为大根堆和排序的过程,时间复杂度主要在大根堆的调整上
* 如果数组开始下标为0,那么左右孩子的下标分别为2*i+1 2*i+2
* 如果开始下标为1,左右孩子的下标分别为2*i 和2*i+1
* @param array 使用堆排序的方式对数字进行排序
*/
public static void HeapSort(int[] array)
{
//非空判断
if(array==null||array.length==0)
{
return;
}
//堆从0位置开始 左孩子元素下标为2*i+1,右孩子节点下标为2*2+2
//最后一个非叶子节点的位置为array.length/2-1
//将堆调整为大根堆 大根堆 为升序
for(int i=array.length/2-1;i>=0;i--)
{
//此处调用调整堆的函数
adjustHeap(array, i, array.length-1);
}
//排序
for(int i=array.length-1;i>=0;i--)
{
//堆顶元素最大 调整到末位置
int temp=array[0];
array[0]=array[i];
array[i]=temp;
//继续调整为大根堆
adjustHeap(array, 0, i-1);
}
}
/*********************
* 将数组调整为大根堆
* @param array 需要进行调整的数组
* @param start 需要调整的开始位置
* @param end 需要调整的结束位置
*/
private static void adjustHeap(int[] array,int start, int end)
{
if(start>=end)
{
return;
}
int temp=array[start];
for(int i=start*2+1;i<=end;i*=2)
{
//查看左右子树中最小的位置
if(i<end&&array[i]<array[i+1])
{
//左子树的值小于右子树的 判断右子树
i++;
}
if(array[start]>=array[i])
{
//右子树的值也小于根节点 说明仍满足大根堆的定义
break;//跳出循环
}
//左右子树中较大的值大于根节点的值 因此需要将根节点的值设置为当前左右节点的较大的值
array[start]=array[i];
start=i; //记录下交换的位置 方便最后将最开始根节点的值交换回来
}
array[start]=temp;//将最开始根节点放到指定的位置
}
堆排序的实现
最新推荐文章于 2020-12-11 19:11:02 发布