堆排序(Java)

堆的特性

完全二叉树,除最后一层节点不需要是满的,其他从左到右都是满的。最后一层不满时,必须遵循“左满右不满”。

通常是用数组实现的

堆排序

首先,创建堆,根据堆的定义,根节点大于两个子节点的叫大根堆(小于则叫小根堆)。然后,利用下层算法,实现删除根节点的方法来实现排序。

时间复杂度

        O(nlogn)

代码示例(此处是以大根堆来建立的堆排序):

public class HeapSort {
    private static boolean less(Comparable[] heap,int i,int j){
        return heap[i].compareTo(heap[j])<0;
    }

    private static void swap(Comparable[] heap,int i,int j){
        Comparable t=heap[i];
        heap[i]=heap[j];
        heap[j]=t;
    }

    private static void createHeap(Comparable[] source,Comparable[] heap){
        /*
            先将数组元素复制到heap中,形成未排序的堆
            再将堆中元素从长度的一半开始,到索引1处进行下沉
         */
        System.arraycopy(source,0,heap,1,source.length);
        for (int i=(heap.length)/2;i>0;i--){
            sink(heap,i,heap.length-1);
        }

    }

    public static void sort(Comparable[] source){
        //创建一个堆数组,长度是原数组长度+1,因为堆数组的第一个索引不存放任何元素
        Comparable[] heap = new Comparable[source.length+1];
        //通过数组建立堆
        createHeap(source,heap);
        //定义一个变量来标志堆中的最大索引
        int i=heap.length-1;
        //通过循环,来交换堆顶和最大索引处的值,将最大值放至最大索引处,不参加下一次循环
        while (i!=1){
            //交换
            swap(heap,1,i);
            /*
              交换完毕,通过下沉算法将剩下元素中的最大值换到堆顶,0~(--i)是指下沉范围                           
              减掉1是为了让最大索引处不参加下沉,因为它已经是最大值了
            */
            sink(heap,1,--i);
        }
        /*
            通过以上过程,此时heap堆中数据已经有序,需将heap复制到原数组source中
         */
        System.arraycopy(heap,1,source,0,source.length);

    }

    public static void sink(Comparable[] heap,int target,int range){
        int max;
        while (2*target<=range){
            if (2*target+1<=range){
                if (less(heap,2*target,2*target+1)){
                    max=2*target+1;
                }else {
                    max=2*target;
                }
            }else {
                max=2*target;
            }
            if (!less(heap,target,max)){
                break;
            }
            swap(heap,target,max);
            target=max;
        }
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值