在了解之前先看一下如何判断一个序列为堆序列。
一、对堆的理解
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序;它的最好、最坏、平均时间复杂度均为O(nlogn),它是不稳定排序。
参考:如何判断一个序列为堆(堆与完全二叉树的关系)
有的文章称大根堆与小根堆,我这里成为最大堆和最小堆。
二、堆排序
例如一个数组中的数据为{2,5,7,3,9}
对应的完全二叉树为:
堆排序过程:
1、初始化堆(将数组对应的二叉树排列成最大堆或最小堆的形式,这里我采用最大堆)
注意:每次交换后都要对下层的子堆进行递归调整,因为交换后有可能破坏已调整子堆的结构。
2、调整堆,采用循环将数组重新排序,每次将根节点的值与堆尾部元素交换,count值每次减一,获得新的无序数组arr[count],被交换的元素再次与它的下一层左右孩子进行比较、调整
对应数组元素为:
3、重复第二步,交换元素之前先调整堆结构
最后数组array={12,9,7,5,3,2};
代码实现:
public static void main(String[] args){
int array={2,5,7,3,9,12};
System.out.println("排序之前,array=");
showArray(array);
initHeap(array);
System.out.println("建堆之后,array=");
showArray(array);
sortHeap(array);
System.out.println("堆排序之后,array=");
showArray(array);
}
//做数组的轮询
private void showArray(int[] array){
for(int i=0;i<array.length;i++){
System.out.print(array[i]);
}
System.out.println();
}
//将组数转换为二叉树形式,同时变成完全二叉树(最大堆或最小堆)
private void initHeap(int[] array){
//开始建堆,从最后一个非叶子节点开始
//注意:最后一个叶子节点的下标(索引)为array.length/2-1;
int root=array.length/2-1;
for(root;root>=0;root--){
adjustHeap(array,array.length,root);
}
}
//调整数组,使之成为完全二叉树(最大堆/最小堆)
public static void adjustHeap(int[] array,int length,int root){
int maxChildIndex;
//待调整子堆的根节点必须是非叶子节点
while(root<count/2-1){
//需要在根root、leftchild、rightchild中找到最大值,然后交换位置
if(root==count/2-1 && count%2==0){//判断节点的个数,如果为偶数,它最后一个非叶子节点没有右子树
maxChildIndex=2*root+1;
}else{
int leftChildIndex=2*root+1;
int rightChildIndex=2*root+2;
if(array[leftChildIndex] < array[rightChildIndex]){
maxChildIndex=rightChildIndex;
}else{
maxChildIndex=leftChildIndex;
}
}
//子节点与根节点进行值比较
if(array[root] < array[maxChildIndex]){
int tem=array[root];
array[root]=array[maxChildIndex];
arrau[maxChildIndex]=tem;
//注意:要继续调整因交换结构而改变的子堆****重新从非叶子节点开始做数组的轮询*******
root=maxChildIndex;
}else{
return;//此刻表示堆结构初始化完成
}
}
public static void sortHeap(int[] array){
initHeap(array);//做一次堆初始化,使之成为完全二叉树
int count=array.length;
while(count>1){
int tem=array[count-1];
array[count-1]=array[0];
array[0]=tem;
count--;//将数组中的第一个数,是本次堆初始化后最大的一个数,取出交换位置,count--,未排序的数字又少了一个
adjustHeap(array,count,0);//参数root=0,调整过程自上而下
}
输出结果:
排序之前,array=
2 5 7 3 9 12
建堆之后,array=
12 9 7 3 5 2
排序之后,array=
12 9 7 5 3 2
多练习! 多练习! 多练习!重要的事情说三遍!