堆排序,和选择排序同属于选择排序类型。
其整体思想为:1 将顶元素和最后一个元素互换。
2 不断将带排序序列构造成为大顶堆或者小顶堆。(大顶堆:每个结点的值都大于或等于其左右孩子结点的值;小顶堆:每个结点的值都小于等于其左右孩子结点的值)
3 堆:满足完全二叉树性质(这点很重要。构建树,大顶堆,小顶堆,都是基于完全二叉树的思想)
主要流程:选择有孩子的结点,作为开始的基准。
将待排序序列构建成为一个大顶堆,其实就是从下向上,从右到左,将每个非中断结点(非叶结点)当做根节点,将其和其子树调整成为大顶堆。
构建大顶堆的过程就是不断的在结点中选择较大的结点,构建大顶堆的过程。(中心思想)
时间复杂度为:O(n log n)
为不稳定的排序方法。
//堆排序,还是有点麻烦。写程序时一定要在脑子里走下树的图,这样子不至于混乱。
public class heapSort3 {
public static void main(String []args){
int a[]={4,6,2,5,8,1,9,7,0,3};
heapSort(a,a.length-1);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
public static void heapSort(int []a,int len){
for(int i=len/2;i>=0;i--){//首先建立一个初始的大顶堆,注意i 的初始值,和条件>=0
heapAdjust(a,i,len); //调整为大顶堆的三个参数,a序列,i 父母结点,len 序列长度
}
for(int i=len;i>=0;i--){ //建立完大顶堆后,从下向上,从左至右的对大顶堆的,最后一个元素和第一个元素进行互换,然后再调整为大顶堆,再互换,最终父母结点值大于左右孩子结点的值。
swap(a,0,i); //其实这里的 i 就是元素逐渐减少的堆的长度(当前调整的大顶堆的长度)
heapAdjust(a,0,i-1);
}
}
public static void heapAdjust(int a[],int parent,int len){
int temp,j;
temp=a[parent];//保存父母结点的值
for(j=2*parent;j<len;j*=2){//对比父母结点和其左右结点的值得大小,找,较大的值和父母结点互换,是循环,对每个父母结点运算,直到没有符合条件的父母结点。
if(j<len&&a[j]<a[j+1]){//左右结点比较
++j;//前加,先加再运算
}
if(temp>=a[j]){//左右结点最大值和父母结点比较
break;
}
a[parent]=a[j];//本句和下句,即为将较大值进行和父母结点的互换操作,并将父母结点的值换做左或右结点互换值的位置,利用for循环继续寻找互换
parent=j;//此处换parent值
}
a[parent]=temp;//互换。
}
public static void swap(int []a,int x,int y){
if(x!=y){
int temp=a[x];
a[x]=a[y];
a[y]=temp;
}
}
}