堆&堆排序

二叉堆

类似于完全二叉树的结构,使用数组来存储元素。
将二叉树的节点按层级顺序放入数组中。
最大堆:每个元素都大于等于其子节点元素的值。
最小堆:每个元素都小于等于其子节点元素的值。
在一个堆中(从0开始计数),位置为k的节点的父节点的位置为(k-1)/2,两个子节点的位置为2k+1和2k+2。
堆的有序化:当堆的状态被打破时,遍历堆将堆的状态恢复。
以下以最大堆为例
当某个节点值增大(如:在堆底加入一个新节点),需要由下至上恢复堆(上浮)

private static void swim(int[] a, int k){
        int parent = (k - 1)/2;
        while (k >= 0 && a[parent] < a[k]){
            exch(a, parent, k);
            k = parent;
            parent = (k - 1) / 2;
        }
    }

当某个节点值减小(如:根节点替换为较小元素),需要由上至下恢复堆(下沉)

private static void sink(int[] a, int k, int len){
        int sub = 2 * k + 1;
        while (sub < len){
            if ((sub + 1 < len) && (a[sub] < a[sub + 1])) sub++;
            if (a[k] >= a[sub]) break;
            exch(a, k, sub);
            k = sub;
            sub = 2 * k + 1;
        }
    }

 
 

堆排序

首先,需要将数据堆化。
然后,不断将堆顶元素交换到当前数组尾,并将剩余元素恢复为堆。

public static void sort(int[] a){
        int N = a.length;

        //建堆 
        //方法一:在堆中每增加一个元素就上浮
        //for (int i = 1; i < N; i++){
        //  swim(a, i);
        //}

        //方法二:除没有子元素的元素外,元素倒序下沉。可减少一半的数据操作。
        for (int i = (N - 1)/ 2; i >= 0; i--){
            sink(a, i, N);
        }

        //交互元素到堆尾,堆不断缩小,数组逐渐有序
        for (int i = N - 1; i > 0; i--){
            exch(a, 0, i);
            sink(a, 0, i);
            show(a);
        }
    }

PS:
堆排序可以用来处理TOPn问题,在内存中维护一个大小为n的最小堆,不断加入新数据。
若新数据比堆顶元素小,不考虑。
若比堆顶元素大,则将堆顶元素替换为新元素,进行下沉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值