1. 堆
堆是一棵顺序存储的完全二叉树。
其中每个结点的关键字都不大于其孩子结点的关键字,这样的堆称为小根堆。
其中每个结点的关键字都不小于其孩子结点的关键字,这样的堆称为大根堆。
对于 n 个元素的序列 {R0, R1, ... , Rn},当且仅当满足下列关系之一时,称之为堆:
(1) Ri <= R2i+1 且 Ri <= R2i+2 (小根堆)
(2) Ri >= R2i+1 且 Ri >= R2i+2 (大根堆)
2. 堆排序
首先,按堆的定义将数组 R[0..n] 调整为堆(这个过程称为创建初始堆),交换R[0]和R[n];
然后,将R[0..n-1]调整为堆,交换R[0]和R[n-1];
如此反复,直到交换了R[0]和R[1]为止。
堆排序中的两个关键问题:
1. 根据初始数组建立初始堆
2. 输出堆顶后,如何“筛选”。
“筛选”:对一棵左、右子树均为堆的完全二叉树,“调整” 根节点使整个二叉树成为堆。
筛选过程:(以小顶堆为例)
首先将该完全二叉树的根结点中的记录移出,该记录称为待 “调整” 的记录。此时根结点相当于空结点,从空结点的左、右孩子中选出一个关键字较小的记录,如果该记录的关键字小于待调整记录的关键字,则将该记录上移至空结点中。
此时,原来那个关键字较小的子结点相当于空结点,从空结点的左、右孩子中选出一个关键字较小的记录,如果该记录的关键字仍然小于待调整记录的关键字,则将该记录上移至空结点中。重复上述移动过程,直到空结点左右孩子的关键字均小于待调整记录的关键字。此时,将待调整的记录放人空结点即可。
建立初始堆:
首先将一个无序列表建立成一棵完全二叉树。然后每个叶子节点可以视为单个元素构成的堆,在利用“筛选”法,自底向上逐层把所有子树调整为堆,直到将整棵完全二叉树调整为堆。
package com.zth.sort;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args){
Integer [] array1 = {3,2,5,8,4,7,6,9};
heapSort(array1);
Double[] array2 = {3.3,2.3,5.3,8.3,4.3,7.3,6.3,9.3};
heapSort(array2);
System.out.println(Arrays.toString(array1));
System.out.println(Arrays.toString(array2));
}
/**
* used in deleteMax and buildHeap
* @int parent the position from which to percolate down
* @int length the logical size fo the binary heap
*/
private static <AnyType extends Comparable<? super AnyType>>
void heapAdjust(AnyType[] array,int parent,int length){
int child = 2*parent+1; // 获取左孩子
AnyType temp = array[parent]; // 保存当前父节点
while (child < length){
// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
if (child + 1 <length && array[child].compareTo(array[child + 1]) <0){
child++;
}
// 如果孩子结点的值大于父结点的值,将孩子节点的值赋给父节点
if (temp.compareTo(array[child]) <0){
array[parent] = array[child];
}else { // 如果父结点的值已经大于孩子结点的值,则直接结束
break;
}
// 选取孩子结点的左孩子结点,继续向下筛选
parent = child;
child = 2 * child + 1;
}
array[parent] = temp;
}
public static <AnyType extends Comparable<? super AnyType>>
void heapSort(AnyType[] array){
// 建立初始堆
for (int i = array.length/2 -1; i >=0; i--) {
heapAdjust(array,i,array.length);
}
// 进行n-1次循环,完成排序
for (int i = array.length-1;i>0;i--){
// 最后一个元素和第一元素进行交换
AnyType temp = array[i];
array[i] = array[0];
array[0]= temp;
heapAdjust(array,0,i);
}
}
}
时间复杂度 | 空间复杂度 | 稳定性 | ||
平均情况 | 最坏情况 | 最好情况 | ||
o(n log n) | o(n log n) | o(n log n) | o(1) | 不稳定 |