堆排序

前言

  • 堆是一个完全二叉树,一层结点满了再把结点添加到下一层,每一层结点的添加顺序是从左到右。
  • 父结点大于或者等于它的任意一个子结点

Heap实现

/**
 * @version 1.0
 * @anthor zsl on 2019/8/8
 * @since jdk8
 */
public class Heap<E extends Comparable<E>> {

    private ArrayList<E> list;


    public Heap(){
        list = new ArrayList<>();
    }

    public Heap(E[] objects){
        list = new ArrayList<>();
        for (E e:
             objects) {
           add(e);
        }
    }

    /**
     * @deprecated 向堆中添加一个元素
     * @param e
     */
    public void add(E e){
        list.add(e);
        int currentIndex = list.size()-1;
        if(currentIndex == 0){

        }
        int parentIndex;
        E parentObject,currentObject;
        while (currentIndex != 0){
            // 获取父元素
            parentIndex = currentIndex/2;
            parentObject  = list.get(parentIndex);
            // 获取子元素的值
            currentObject = list.get(currentIndex);

            if(parentObject.compareTo(currentObject) < 0){
                list.set(parentIndex,currentObject);
                list.set(currentIndex,parentObject);
                currentIndex = parentIndex;
            }else {
                break;
            }
        }
    }

    /**
     * @deprecated 删除堆顶
     * @return E
     */
    public E remove(){

        if(list.size() == 0){
            return null;
        }
        // 当前下标是数组做大下标
        int currentIndex = list.size()-1;

        /*记录根节点值并把最后一个节点覆盖到根节点,把当前结点重置成为根节点*/
        E object = list.get(0);
        list.set(0,list.get(currentIndex));
        list.remove(currentIndex);
        currentIndex = 0;

        /*求出当前节点的左孩子与右孩子结点下标*/
        int leftIndex = currentIndex*2+1;
        int rightIndex = currentIndex*2 +2;
        int limit = list.size()-1;

        /*如果当前结点为叶子结点则退出循环*/
        while (leftIndex < limit && rightIndex <= limit){

            /*获取当前结点、左孩子结点、右孩子结点的值*/
            E currentObject = list.get(currentIndex);
            E leftObject = list.get(leftIndex);
            E rightObject = list.get(rightIndex);

            // 如果当前结点小于左孩子结点
            if(currentObject.compareTo(leftObject) < 0){
                list.set(currentIndex,leftObject);
                list.set(leftIndex,currentObject);
                currentIndex = leftIndex;
            }else if(currentObject.compareTo(rightObject) < 0) {
                // 如果当前结点小于右孩子结点的值
                list.set(currentIndex,rightObject);
                list.set(rightIndex,currentObject);
                currentIndex = rightIndex;
            }else {
                // 如果当前结点既不小于左孩子结点又不小于右孩子结点的值
                break;
            }

            //重置左孩子、右孩子的下标
             leftIndex = currentIndex*2+1;
             rightIndex = currentIndex*2 +2;
        }
        return object;
    }

    /**
     * @deprecated 堆的大小
     * @return int
     */
    public int size(){
        return list.size();
    }
}

测试

 public static void main(String[] args) {

        Integer[] arr = {10,5,2,7,3,1,2};
        System.out.println(Arrays.toString(execute(arr)));
    }

    public static Integer[] execute(Integer[] arr){
        Heap<Integer> heap = new Heap<>(arr);
        for(int i = arr.length-1; i >= 0; i--){
            arr[i] = heap.remove();
        }
        return arr;
    }
时间复杂度平均情况时间复杂度最优情况时间复杂度最差情况空间复杂度稳定性
O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值