java常用算法之堆排序

堆排序,是一种运用数组来存储数据,但是对元素排序时却使用了二叉树结构思想来进行排序的算法。

排序中的堆实际上就是一个完全二叉树的结构,完全二叉树的概念我之前说过,这里就不再赘述,二叉树中,元素中若双亲节点比孩子节点大,那么就是大根堆,若小,那么就是小根堆。

堆排序的思想:完全二叉树中节点之间关系明确,节点 i 的左右孩子分别是 2i 和 2i+1(这是节点元素在数组中从索引为1开始存储的对应关系),若从0开始,那么对应关系就是 i  2i+1(左孩子) 2i+2(右孩子),因此完全可以使用数组来表示二叉树结构

堆排序实现方式:

1.元素下沉:当大根堆中双亲节点比孩子节点小的时候我们需要交换两者之间的位置,这就是元素下沉,也可以理解为元素交换

2.运用元素下沉来构建大根堆

3.构建好大根堆,首尾元素交换,数组长度减一,重新构建大根堆

堆排序代码(推荐大家从exc方法开始看,充分理解上面的三个步骤,否则很难理解堆排序,大神除外。。。):

package sort;

import com.sun.org.apache.regexp.internal.recompile;

//堆排序
//思路:先将数组调整为大根堆或者小根堆
//接着将堆中最大的跟堆中最后一个元素交换位置
//之后调整堆中元素的位置,重新构成堆结构
public class heapSort {
    //交换根节点和最后一个节点的位置
    //堆中的数量减一,因为最大的已经在数组的最后面
    //此时破坏了堆的结构,再次创建大根堆
    public static void reMkHeap(int[] a){
        int num = a.length;
        //确定遍历次数,也就是大根堆构建好以后
        //首位交换的次数,比如5个数,
        // 那么需要交换4次调整四次大根堆
        for(int i = 0;i<a.length-1;i++){
            //调整为大根堆
            mkHeap(a,num--);

            //首尾交换
            exc(a,0,num);
        }
    }
    //创建大根堆
    //策略就是:从array.length/2-1开始遍历,因为只有这个位置
    //才有子节点
    public static void mkHeap(int[] a,int length){
        //从array.length/2-1开始嵌套的遍历数组
        for(int i = length/2-1;i>=0;i--){
            for(int j = i;j<=length/2-1;j++){
                //比较父节点和左右孩子的大小
                //这里判断是因为当我们构建好大根堆的时候
                //由于收尾元素交换,再次构建大根堆的时候
                //我们是不需要跟堆中的a[length-1] a[length-2]...
                //这些已经有大小关系的数交换的
                if(2*j+1<length){
                    compare(a,j,2*j+1);
                }
                if(2*j+2<length){
                    compare(a,j,2*j+2);
                }
            }
        }
    }
    //比较元素,相当于元素下沉方法
    public static void compare(int[] a,int parent,int childs){
        int temp;
        if(a[parent]<a[childs]){
            temp = a[parent];
            a[parent] = a[childs];
            a[childs] = temp;
        }
    }
    //首尾元素交换,此时已是大根堆,无需比较
    public static void exc(int[] a,int first,int last){
        int temp = a[last];
        a[last] = a[first];
        a[first] = temp;
    }
    public static void main(String[] args) {
        int[] a = {8,3,0,1,2};
        reMkHeap(a);
        for(int i : a){
            System.out.println(i);
        }
    }
}
运行结果:
E:\jdk1.8\bin\java "-javaagent:E:\idea\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=51566:E:\idea\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=GBK -classpath E:\jdk1.8\jre\lib\charsets.jar;E:\jdk1.8\jre\lib\deploy.jar;E:\jdk1.8\jre\lib\ext\access-bridge-64.jar;E:\jdk1.8\jre\lib\ext\cldrdata.jar;E:\jdk1.8\jre\lib\ext\dnsns.jar;E:\jdk1.8\jre\lib\ext\jaccess.jar;E:\jdk1.8\jre\lib\ext\jfxrt.jar;E:\jdk1.8\jre\lib\ext\localedata.jar;E:\jdk1.8\jre\lib\ext\nashorn.jar;E:\jdk1.8\jre\lib\ext\sunec.jar;E:\jdk1.8\jre\lib\ext\sunjce_provider.jar;E:\jdk1.8\jre\lib\ext\sunmscapi.jar;E:\jdk1.8\jre\lib\ext\sunpkcs11.jar;E:\jdk1.8\jre\lib\ext\zipfs.jar;E:\jdk1.8\jre\lib\javaws.jar;E:\jdk1.8\jre\lib\jce.jar;E:\jdk1.8\jre\lib\jfr.jar;E:\jdk1.8\jre\lib\jfxswt.jar;E:\jdk1.8\jre\lib\jsse.jar;E:\jdk1.8\jre\lib\management-agent.jar;E:\jdk1.8\jre\lib\plugin.jar;E:\jdk1.8\jre\lib\resources.jar;E:\jdk1.8\jre\lib\rt.jar;E:\untitled1\out\production\untitled1 sort.heapSort
0
1
2
3
8


Process finished with exit code 0
 
 public static void main(String[] args) {
        int[] a = {1,2,3,4,5};
        reMkHeap(a);
        for(int i : a){
            System.out.println(i);
        }
    }
}

运行结果:
E:\jdk1.8\bin\java "-javaagent:E:\idea\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=52290:E:\idea\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=GBK -classpath E:\jdk1.8\jre\lib\charsets.jar;E:\jdk1.8\jre\lib\deploy.jar;E:\jdk1.8\jre\lib\ext\access-bridge-64.jar;E:\jdk1.8\jre\lib\ext\cldrdata.jar;E:\jdk1.8\jre\lib\ext\dnsns.jar;E:\jdk1.8\jre\lib\ext\jaccess.jar;E:\jdk1.8\jre\lib\ext\jfxrt.jar;E:\jdk1.8\jre\lib\ext\localedata.jar;E:\jdk1.8\jre\lib\ext\nashorn.jar;E:\jdk1.8\jre\lib\ext\sunec.jar;E:\jdk1.8\jre\lib\ext\sunjce_provider.jar;E:\jdk1.8\jre\lib\ext\sunmscapi.jar;E:\jdk1.8\jre\lib\ext\sunpkcs11.jar;E:\jdk1.8\jre\lib\ext\zipfs.jar;E:\jdk1.8\jre\lib\javaws.jar;E:\jdk1.8\jre\lib\jce.jar;E:\jdk1.8\jre\lib\jfr.jar;E:\jdk1.8\jre\lib\jfxswt.jar;E:\jdk1.8\jre\lib\jsse.jar;E:\jdk1.8\jre\lib\management-agent.jar;E:\jdk1.8\jre\lib\plugin.jar;E:\jdk1.8\jre\lib\resources.jar;E:\jdk1.8\jre\lib\rt.jar;E:\untitled1\out\production\untitled1 sort.heapSort
1
2
3
4
5


Process finished with exit code 0

 public static void main(String[] args) {
        int[] a = {5,4,3,2,1};
        reMkHeap(a);
        for(int i : a){
            System.out.println(i);
        }
    }

}

运行结果:
E:\jdk1.8\bin\java "-javaagent:E:\idea\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=52290:E:\idea\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=GBK -classpath E:\jdk1.8\jre\lib\charsets.jar;E:\jdk1.8\jre\lib\deploy.jar;E:\jdk1.8\jre\lib\ext\access-bridge-64.jar;E:\jdk1.8\jre\lib\ext\cldrdata.jar;E:\jdk1.8\jre\lib\ext\dnsns.jar;E:\jdk1.8\jre\lib\ext\jaccess.jar;E:\jdk1.8\jre\lib\ext\jfxrt.jar;E:\jdk1.8\jre\lib\ext\localedata.jar;E:\jdk1.8\jre\lib\ext\nashorn.jar;E:\jdk1.8\jre\lib\ext\sunec.jar;E:\jdk1.8\jre\lib\ext\sunjce_provider.jar;E:\jdk1.8\jre\lib\ext\sunmscapi.jar;E:\jdk1.8\jre\lib\ext\sunpkcs11.jar;E:\jdk1.8\jre\lib\ext\zipfs.jar;E:\jdk1.8\jre\lib\javaws.jar;E:\jdk1.8\jre\lib\jce.jar;E:\jdk1.8\jre\lib\jfr.jar;E:\jdk1.8\jre\lib\jfxswt.jar;E:\jdk1.8\jre\lib\jsse.jar;E:\jdk1.8\jre\lib\management-agent.jar;E:\jdk1.8\jre\lib\plugin.jar;E:\jdk1.8\jre\lib\resources.jar;E:\jdk1.8\jre\lib\rt.jar;E:\untitled1\out\production\untitled1 sort.heapSort
1
2
3
4
5


Process finished with exit code 0

大家也可以优化一下,先让双亲的两个孩子比较大小,之后在跟双亲比较大小然后交换。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值