1.基本原理
在堆中,左孩子的位置等于父节点位置的二倍加一。然后循环 从右子树开始,首先判断左右孩子中哪个孩子值 较大,然后将 大的值与父节点的值进行比较,若孩子的值大于父节点的值,则将两值互换,然后孩子当爹,如此循环将大的值作为父节点。(构成大顶堆)最大值成为顶点 后,将顶点与末尾进行对换。然后把末尾的位置剔出函数,剩下的 数组重新构成大顶堆,如此循环。
2.代码实现
public static void heap(int[] arr)
{ //堆排序 1、先创建堆
for(int i=(arr.length-1) / 2; i>=0; i--) //从数组中间的值开始,先作为顶点,然后从右边到左边,从上到下调整堆结构
{
adjust(arr,i,arr.length); //结束后形成了大顶堆
}
for(int i=arr.length-1 ; i>0 ; i--) //交换堆顶元素与末尾元素后 再调整堆结构,构成大顶堆
{
int temp=arr[i];
arr[i]=arr[0];
arr[0]=temp;
adjust(arr,0,i); //将最大的那个放在末尾,不进行调整
}
}
public static void adjust(int[] arr,int parent,int length)
{ //2、调整堆结构(大顶堆)
int father=arr[parent]; //把temp作为父节点
int lChild=2*parent+1; //父节点的左孩子
while (lChild<length) //如果左孩子小于数组长度,说明存在右孩子
{
int rChild=lChild+1; //右孩子比左孩子大一
if(rChild<length && arr[lChild] < arr[rChild]) //如果右孩子依然存在,且右孩子值大于左孩子,则选右孩子节点
{
lChild++; //左孩子结点始终指向大的节点
}
if(father >= arr[lChild]) //如果父节点大于孩子节点中较大的那个,则结束循环
{
break;
}
arr[parent]=arr[lChild]; //否则把孩子的值赋给父亲
parent=lChild; //然后孩子当爹,往下筛选
lChild=2*lChild+1; //然后把左孩子换成新爹的左孩子
arr[parent]=father; //最后将值交换
}
}