算法——排序之堆排序

堆排序也是根据比较来排序的。堆排序效率很高的,时间复杂度为O(nlgn),因为是利用二叉树索引来进行建堆。

堆包括大顶堆和小顶堆两种。

堆排序包括3步:建堆;整堆;取值。

建堆:

         通过数组中的下标来建立索引是数组中的数值在纵向看来是一个二叉树——时间复杂度为O(lgn);

然后从后向前 对非叶子节点进行整堆——(O(n))。

整堆:

         通过 比较父节点与左右孩子节点数值的大小,来交换大(小)的值,达到从上到下 父节点的值大(小)于左右孩子节点的值。

堆排序在根据上述建好的堆 依次  获得  最大(小)的根节点的值再把 数组长度减1,这样就得到有序的数组了。

取值:

        每次整堆后取根植,即可得有序数组。

下面看看代码:

public class HeapSort {    // 这里使用的是大顶堆

    public static void swap(int [] a,int i,int j){
        int temp = a[i];
        a[i] = a[j];
        a[j]= temp;
    }

    public static void buildHeap(int [] a){
        int len = a.length;
        for(int i = (len/2)-1;i>=0;i--){     //数组下标 从0开始 需 -1
            fixHeap(a,i);
        }
    }

    public static void fixHeap(int [] a,int i){  // 注意 数组从0开始时 是 left = 2i+1 ;  要是处理后从1开始时 应该为 left = 2i
        int left = 2*i+1;
        int right = left+1;
        int max = i;                            // max 标记 father, left, right 3者较大者

        if(left<=a.length-1 && a[left]>a[max]){   
            max = left;
        }
        if(right<=a.length-1 && a[right]>a[max]){
            max = right;
        }
        if(i!=max){                             // 若是father 比 left 或者right 小的话 则 一直向下整堆 使下面始终保持堆的性质
            swap(a,i,max);
            fixHeap(a,max);
        }
    }

    public static int [] sort(int [] a){
        int len = a.length-1;
        buildHeap(a);
        int [] b = new int [a.length];       // 因为数组是没办法长度-1的  所以 不能获得根数值后   减少长度继续 整堆  这里用b[]来存储根数值
        int j=0;
        for(int i=len;i>=0;i--){
            b[j++] = a[0];
            a[0] = -1;                      // 将a[0] 变成最小的值 -1(仅供参考) 然后就能继续进行整堆 始终能找出剩下数值中最大的了。
            fixHeap(a,0);
        }
        return b;
    }

    public static void main(String[] args) {
        int [] a = {3,2,6,4,9,5,0,1,7,8};
        for(int i:a){
            System.out.print(i + " ");
        }
        System.out.println();
        a = sort(a);
        for(int i:a){
            System.out.print(i + " ");
        }
    }
}
结果不言而喻,肯定能排序的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值