最大堆$堆排序

完全二叉树

在这里插入图片描述

完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。

完全二叉堆

结构上是完全二叉树,并且满足堆序性,也就是父节点的值要不小于(大顶堆)或不大于(小顶堆)子节点的值。

大顶堆
package com.kyrie.test.heap;

import java.util.ArrayList;

/**
 * @author kyrie
 */
public class MaxHeap {

    private ArrayList<Integer> nums = new ArrayList<>();

    public MaxHeap() {
    }

    public MaxHeap(ArrayList<Integer> nums) {
        this.nums = nums;
        this.constructHeap();
    }

    /**
     *
     * @return 仅返回最大的数,即第一个数
     * @throws Exception
     */
    public int getMax() throws Exception {
        if(nums.size()<=0) throw new Exception();
        return nums.get(0);
    }

    /**
     *
     * @return  Max
     * @throws Exception
     * 将第一个数返回后,把最后一个数替换第一个数,再检测下滤
     */
    public int deleteMax() throws Exception {
        if(nums.size()<=0) throw new Exception();
        int res=nums.get(0);
        nums.set(0,nums.get(nums.size()-1));
        nums.remove(nums.size()-1);
        this.percolateDOwn(0);
        return res;
    }

    /**
     *
     * @param ele
     * 加入一个元素到数组末尾,然后上浮
     */
    public void add(int ele){
        int len = nums.size();
        nums.add(ele);
        this.upRise(len);
    }
    /**
     *
     * 将最后一个节点,与其父节点比较,递归上浮
     */
    private void upRise(int i){
        if(i==0) return;
        int parent=i/2;
        if(nums.get(i)>nums.get(parent)){
            swap(parent,i);
            upRise(parent);
        }
        return;
    }

    /**
     *
     * 从倒数第一个内部节点开始下滤,使得整个堆有序
     */
    public void constructHeap(){
        int len=nums.size();
        // 最后一个内部节点的下标
        int lastInternal = len/2-1;
        // 从下往上下滤,按照弗洛伊德算法,时间复杂度为O(n)
        for (int i = lastInternal; i >= 0; i--) {
            this.percolateDOwn(i);
        }
    }

    /**
     *
     * @param i 将被下滤的数
     */
    private void percolateDOwn(int i ){
        int last = this.nums.size();
        int L = i * 2+1;
        int R = L + 1;
        int minLR = -1;
        if (L >= last && R >= last) {//如果当前节点为叶子节点,下滤结束
            return;
        }
        if (L < last && R >= last) {
            minLR = L;
        }else{
            minLR = this.nums.get(L) < this.nums.get(R) ? R : L;

        }

        if (this.nums.get(i)>= this.nums.get(minLR)) {//不需要下滤
            return;
        } else {
            swap(i,minLR);
            this.percolateDOwn(minLR);//继续下滤
        }
    }
    private void swap(int i,int j){
        int temp=nums.get(i);
        nums.set(i,nums.get(j));
        nums.set(j,temp);
    }

    public int size(){
        return nums.size();
    }

    public static void main(String[] args) throws Exception {

        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(4);
        arrayList.add(56);
        arrayList.add(21);
        arrayList.add(-76);
        arrayList.add(100);
        arrayList.add(42);
        MaxHeap maxHeap = new MaxHeap(arrayList);
        System.out.println(maxHeap.deleteMax());
        System.out.println(maxHeap.deleteMax());
        System.out.println(maxHeap.deleteMax());
    }
}

小顶堆

小顶堆的构建方式和大顶堆大同小异,就不展示构建代码

堆排序(T:O(nlogn),S:O(1))
package com.kyrie.test.heap;

public class HeapSort{

        public  void heapSort(int[] nums) {
                for (int j = nums.length-1; j > 0; j--) {
                    int t = nums[j];
                    nums[j] = nums[0];
                    nums[0] = t;
                    this.percolateDOwn(0, nums, j );
                }
                }
        private void percolateDOwn(int i, int[] nums, int last) {
                int L = i*2+1;
                int R = L + 1;
                int minLR = -1;
                if (L >= last && R >= last) {//如果当前节点为叶子节点,下滤结束
                return;
                }
                if (L < last && R >= last) {
                minLR = L;
                }
                if (L < last && R < last) {
                minLR = nums[L] < nums[R] ? R : L;
                }
                if (nums[i] >= nums[minLR]) {//不需要下滤
                    return;
                } else {
                int t = nums[i];
                nums[i] = nums[minLR];
                nums[minLR] = t;
                this.percolateDOwn(minLR, nums, last);//继续下滤
                }
                }

        public void heapify(int[] nums) {
                // 最后一个内部节点的下标
                int lastInternal = nums.length/2-1;
                // 从下往上下滤,按照弗洛伊德算法,时间复杂度为O(n)
                for (int i = lastInternal; i >= 0; i--) {
                    this.percolateDOwn(i, nums, nums.length);
                }

        }


            public static void main(String[] args) {

                int[] nums = new int[] { 8,4,2,9,5,9,467,-4,3};
                HeapSort heapSort = new HeapSort();
                heapSort.heapify(nums);

                heapSort.heapSort(nums);
                System.out.println("kyrie");


        }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值