当前位置 博文首页 > Arthur_____的博客:堆排序(HeapSort)详解
用法区别:
arr[i]
来说:arr[2*i+1]
表示它的左孩子节点arr[2*i+2]
表示它的右孩子节点len
的堆来说:arr[len/2+1]
由以上特点我们可以得到堆的特性:
arr[i] >= arr[2*i+1] && arr[i] >= arr[2*i+1]
arr[i] <= arr[2*i+1] && arr[i] <= arr[2*i+1]
adjustHeap()
方法;
adjustHeap(int[] arr, int i, int len)
的作用:
- 将以
i
为根节点、长度为len的数据,调整为一个大顶堆;
调用
adjustHeap()
方法的条件:
- 传入的以
i
为根节点的数据,必须要蛮子:只要将i
与某个节点交换一轮位置,即可以得到一个大顶堆。
adjustHeap()
方法的条件分析:
- 首先,那个“最深”“最右”的非叶子节点作为
i
,显然满足条件;其最多只有3个元素;- 其次,按照“从右至左,从上至下”的调整顺序,显然也满足条件;
- 故该顺序调用
adjustHeap()
方法可以得到一个大顶堆;
那么,具体来说adjustHeap()
方法是如何发挥作用的呢?
下面借助一个例子来帮助大家理解该方法的作用。
完整:
adjustHeap()
方法的条件的!! private void heapSort(int[] arr) {
int len = arr.length;
//1、首先,构造一个大顶堆:
for(int i=len/2-1;i>=0;i--){
//首先,这个最深的非叶子节点为根的结构,满足条件可以调用adjustHeap
adjustHeap(arr,i,len);
//然后,按照从右到左,从上到下的顺序调整(i--),就可以保证每个i都满足adjustHeap的条件
}
//2、循环:
// a.更换最大值(索引=0)和末尾元素(选择排序)
// b.调整前面len-1的结构为大顶堆
for(int i = len-1; i > 0 ; i --){
//把最大值放到末尾去
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//调整前面的结构为大顶堆
//此时,以0为根节点的结构,是可以直接调整的
adjustHeap(arr,0,i);
}
// 调整完毕!
}
/**
* 将符合条件的,以 i 为根节点的,长度为length的结构调整为堆!!
*
* @param arr 数组
* @param i 要调整的根节点
* @param length 要调整的数组长度
*/
private void adjustHeap(int[] arr, int i, int length) {
//把这个要调整的先放起来存着
int temp = arr[i];
//最开始的k是i的左节点
//后面递归找自己的左节点
for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
//首先,保证k指向的是i的左右节点里面最大的
if(k+1 < length && arr[k] < arr[k+1]){
k++;
}
if(arr[k] > temp){
//如果这个“最大的左右子节点k”的值,他比我们现在的“根节点”更大,那么就得就换上去嘛;因为现在的k是左右子节点中的一个
arr[i] = arr[k];
//然后呢,要把i的位置也换到这个“最大的左右子节点k”上去;
//这样做是为了下一层找下一个i的“最大的左右子节点k”
i = k;
}else {
//如果现在这个“最大的左右子节点k”的值,小于等于之前的“根节点”的话呢;
//说明当前的temp,放到k这一层的上一层就对了!(上一层要比下一层大或者等于)
break;
}
}
arr[i] = temp;
}
cs