堆排序
一、首先先解释一下什么是堆?
堆可以看做是一颗树,而且是一颗完全二叉树。不同的二叉树请看下图:
二、堆排序的特性
首先介绍复杂度:
时间复杂度:O(nlgn)…
空间复杂度:O(1)
鉴于堆这种数据结构本身的特性可以发现(以最大堆为例),根节点为数组中最大元素,左右子节点小于等于根节点。
另外,假设某个元素为序号为i(Java数组从0开始,i为0到n-1), 如果它有左子树,那么左子树的位置是2i+1,如果有右子树,右子树的位置是2i+2,如果有父节点,父节点的位置是(n-1)/2取整。
三、堆排序步骤
堆排序主要分为两步:
1. 根据数组构建一个堆
2. 排序
直接上代码
public class HeapSort {
static int N = 0;
public static void main(String[] args) {
int array[]={5,1,3,11,2,6,7,8,4,9,10,12};
N = array.length;
printArray(array);
buildHeap(array);
sort(array);
}
private static void sort(int[] array) {
System.out.println("开始排序...");
for(int i=N-1;i>=1;i--){
exch(array,0,i);//交换根元素和尾元素
adjustHeap(array,i,0);
}
System.out.println("排序完毕!结果如下:");
printArray(array);
}
private static void buildHeap(int[] array) {
System.out.println("开始构建堆...");
//构建堆
for(int i=(array.length-1)/2;i>=0;i--){
//从最后一颗子树开始
adjustHeap(array,array.length,i);
}
System.out.println("堆构建完毕!结果如下:");
printArray(array);
}
private static void printArray(int[] array) {
for(int n:array){
System.out.print(n+",");
}
System.out.println("");
}
/**
* Parent = (k-1)/2
* Left = 2i+1;
* Right = 2i+2;
* @param a 数组
* @param k 下标
*/
private static void adjustHeap(int[] a,int length,int k){
while(2*k+2 <= length ){
int left = 2*k+1;
int max = left;
if(left + 1 < length){
int right = left+1;
if(less(a,left,right)){
max = right;
}
}
if(less(a,max,k)){
break;
}
exch(a,k,max);
printArray(a);
k = max;
}
}
private static boolean less(int[] a,int i,int j){
return a[i]<a[j];
}
private static void exch(int[] a,int i,int j){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
以上就是堆排序的Java实现代码,基本思想就是先构建堆,从最后一个子树开始逐一构建;当堆构建完毕之后,基于最大堆的特性,把根元素和最后一个未排序的元素互换,交换完毕后再重新构建堆。
注:如果想要倒序排列数组,则需要构建最小堆,把代码中的less方法修改成>即可。