堆:一个完全二叉树
大顶堆:一个二叉树,它的根节点上的值是整个树上最大的
小顶堆:它的根节点上的值是整个树上最小的
大致思路如下(升序排列):将一个数据视为一个二叉树,树根的角标为零,角标为n的位置的左子节点的角标为2*n+1,右子节点的角标为2*n+2。假设我们要排序数组中的前N个数,我们就将前n个树构造成一个大顶堆,然后树根(nums[0])就是最大的,将nums[0]与nums[n-1]交换,然后对前n-1个重复上述操作。直至n=0,排序完成。
代码如下:
package Sort;
import java.util.Arrays;
本程序为堆排序
堆:一个完全二叉树
大顶堆:一个二叉树,它的根节点上的值是整个树上最大的
小顶堆:它的根节点上的值是整个树上最小的
大致思路如下(升序排列):将一个数据视为一个二叉树,树根的角标为零,角标为n的位置的左子节点的角标为2*n+1,右子节点的角
标为2*n+2。假设我们要排序数组中的前N个数,我们就将前n个树构造成一个大顶堆,然后树根(nums[0])就是最大的,将nums[0]与nums[n-1]交换,
然后对前n-1个重复上述操作。直至n=0
public class HeapSort {
/**
*
* @param nums 需要构造大顶堆的数组
* @param i 需要构造大顶堆的树的树根在nums数组中的角标,该树可能是nums数组构成的二叉树中的一个子树,也可能就是数组构成的树
* (当i=0的时候)
* @param length 数组的最后一位数的角标
*/
该方法只是将数组组成的二叉树中的某个子树构造成一个大顶堆,并不是将整个数组构造成大顶堆
public static void heapBuild(int nums[],int i,int length){
//在将以i为树根的树构造成大顶堆的时候,默认i的左子树和右子树均为大顶堆
int temp=nums[i];
int j;
for(j=2*i+1;j<=length;j=j*2+1){
因为i的左子树和右子树均为大顶堆,所以下面这个if语句执行完毕之后,nums[j]就是i的子树中的最大值
if(j+1<=length&&nums[j]<nums[j+1])
j++;
if(temp>=nums[j]){
因为i的左子树和右子树均为大顶堆,所以nums[j]就是i的子树中的最大值,由于temp>=nums[j],说明此时树根的值已经该子树的最大值
也就是说该子树已经是一个大顶堆,直接结束
break;
}else{
说明i位置上不是最大值,整个子树的最大值就是nums[j],将最大值赋予nums[i]
nums[i]=nums[j];
为什么要进行赋值操作,而不是进行数据的交换? 举一个例子
4
10 5
9 5 3 1
假如我们要将该树做成一个大顶堆,headBuild(nums,0,6)
我们直到以10和5为根节点的子树已经都是大顶堆了,执行到nums[i]=nums[j]之后的树如下图所示
10
10 5
9 5 3 1
这个时候temp还等于4,我们还得在该树中找到temp的位置,但是如何找到temp的位置呢?
思路如下:
因为我们把nums[j]赋值给nums[i],所以以角标j的跟根节点的子树相当于少了一个树,所以我们只需要将temp放在该树中就可以。
将temp的值与j的左子节点和右子节点作比较,如果temp最大,直接将他放在该位置上,直接结束;如果小于,直接将最大值放在该位置上,
然后重复上述操作
i=j;
所以你看,其实第二个if 要将左右节点的值与temp相比,是不是其实这个方法的作用就是在为temp在大顶堆中找到一个位置。
}
}
nums[i]=temp;
}
public static void heapSort(int nums[]){
从最后一个非叶子节点开始将整个数组构成一个大顶堆
for(int i=nums.length/2-1;i>=0;i--){
heapBuild(nums,i, nums.length-1);
}
for(int i=nums.length-1;i>=0;i--){
在这个时候整个数组就是一个大顶堆
int temp=nums[0];
nums[0]=nums[i];
nums[i]=temp;
除了角标为零的树,其余子树全是大顶堆,所以直接从零调整大顶堆
heapBuild(nums,0,i-1);
}
System.out.println(Arrays.toString(nums));
}
public static void main(String[] args) {
int nums[]={10,41,48,2,1,1,0};
// heapBuild(nums,0,nums.length-1);
// System.out.println(Arrays.toString(nums));
heapSort(nums);
}
}