堆排序(以大顶堆 升序为例为例)
没有图,就是根据自己理解理清最简单得思路
首先是要明确 大顶堆 小顶堆
- 大顶堆:每个节点都大于或等于左右子节点(升序用它!)
- 小顶堆:每个节点都小于或等于左右子节点(降序用它!)
先说过程:
- 创先两个方法,一个用来调整二叉树的结构,一个是用来排序
- 在调整中,取得是左右节点最大得节点和需要调整节点做判断
- 等二叉树满足条件后,就开始排序,将第一个点放到最后,数组长度减一
- 然后再将交换后的二叉树进行调整,使得满足结构
- 再反复进行3、4步骤,就完成了排序
以上有个问题(即思路)
怎么和子节点做判断
- 当前节点为2*sit(root节点为0),每个节点的左右节点为2*sit+1或者2*sit+2,所以需要调整得节点为tmp,所以先取左右节点最大得值再和tmp做判断,做交换,将tmp赋值给小的节点,然后再调整结构,当然这个要循环整个树得深度。跳出条件为当前值大于判断的根节点。
注意要记录上一个值 和当前值 s=lOr, lOr = lOr*2+1
直接看代码吧
public class Heap {
public static void swap(int[] num,int start, int end){
// 初始位置
int s = start;
//取的左右节点较大的点的位置
int lOr = 2*s+1;
//记录临时值 用于后面交换
int tmp = num[s];
//当点的值大于数组长度跳出,s作为记录上一个值,lOr作为下一个值,当满足条件后就做交换,这次的点就赋值为tmp
for(;lOr <= end; s=lOr, lOr = lOr*2+1){
if(lOr < end && num[lOr] < num[lOr+1]){
lOr++;
}
if(tmp >= num[lOr]){
break;
}else {
num[s] = num[lOr];
num[lOr] = tmp;
}
}
}
public static void heapSort(int[] num, int len){
int i, tmp;
//先调树结构
for(i = len/2-1; i >= 0; i--){
swap(num,i,len-1);
}
for(i = len - 1; i > 0; i--){
tmp = num[0];
num[0] = num[i];
num[i] = tmp;
//排序好一个就调整一次树的结构
swap(num,0,i-1);
}
}
public static void main(String[] args) {
int a[] = {1,3,8,2,4,6,11,10,7,9,5};
System.out.printf("排序前:");
for (int i=0; i<a.length; i++)
System.out.print(a[i]+" ");
System.out.printf("\n");
heapSort(a, a.length);
System.out.printf("排序后:");
for (int i=0; i<a.length; i++)
System.out.print(a[i]+" ");
System.out.printf("\n");
}
}
堆排序不是稳定的排序! 完事儿下班!