目录
一、大顶堆
- 必须是完全二叉树
- 父节点的值必须大于其子节点的值
二、利用大顶堆排序
2.1 思路分析
A:给定一个数组,将该数组看作一棵虚拟的完全二叉树;
B:将该数组构造成一个大顶堆
a:找到最后一个非叶子节点,比较该节点的值与其子节点的值,将父节点的值与最大值进行交换,完成局部大顶堆;
b:局部大顶堆的按照"从右向左,从下至上"的原则进行,比如上面这个图,i=3时,完成局部大顶堆后,i应该变成2
来完成上层右侧的局部大顶堆,以此类推,当i=0时,就完成最上层的大顶堆;
c:就下图步骤3而言,9与4交换后,下面的大顶堆就不成立了,所以还需要重新构造;
C:将大顶堆的最上面的值与最末尾的元素交换,也就是交换数组的首尾元素;
D:交换结束后,末尾元素是最大值就不要动了,对数组的前n-1个元素,重新构造大顶堆
a:这时候就不是找最后一个非叶子节点了,因为当前是除了堆顶外,其余子树都是局部大顶堆的形式,所以直接从
从堆顶开始构造,重复步骤C,直到数组排序完成;
2.2 大顶堆升序排序
/**
* 利用堆排序,实现数组的升序
* @author Administrator
*
* 分析
* A:给定一个数组,将该数组看作一棵虚拟的完全二叉树;
* B:定义adjustHeap方法,目的是从当前非叶子结点与其孩子中选出最大值;
* C:定义堆排序方法heapSort,首先构造大顶堆,然后将最大的元素与末尾的
* 元素进行交换,除去末尾元素,重新构造大顶堆,反复执行。
*
*
*/
public class HeapSort {
public static void main(String[] args) {
int[] arr = {4,6,8,5,9};
heapSort(arr);
}
/**
* 这个方法用来构造局部大顶堆
* @param arr
* @param i
* @param length
*/
public static void adjustHeap(int[] arr,int i,int length) {
int temp = arr[i];
for(int k = i*2+1; k < length; k = i*2+1) {
if(k+1 < length && arr[k] < arr[k+1]) {
k++;
}
if(arr[k] > temp) {
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = temp;
}
/**
* 这个方法用来实现堆排序
* @param arr 待排序的数组
*/
public static void heapSort(int[] arr) {
int temp;
for(int i = arr.length/2-1; i >= 0; i--) {
adjustHeap(arr,i,arr.length);
}
for(int j = arr.length-1; j > 0; j--) {
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr,0,j);
}
System.out.println("数组:"+Arrays.toString(arr));
}
}
2.3 小顶堆降序排序
- 这个就是将构造大顶堆的大于号改成小于号就行了;
三、总结
- 关于堆排序还未理解,尤其是代码,很神奇的感觉,关键在于i=k这条语句上;
- 接下来尝试学习堆排序的不同实现方式来加深理解