数据结构---堆

一棵完全二叉树,并且双亲节点的值大于(小于)等于子节点的值,这样的二叉树成为大堆(小堆)。
堆在物理上是一个数组,其作用是找到一组数据中的最大值。
已知双亲下标parent:则左孩子下标:left=2parent+1;右孩子的下标:right=2parent+2

堆的用处

1.解决优先级队列问题(如果vip值相等,无法保证先来先服务)
2.排序:
3.topK问题:在海量数据中,找到最大数量级的k个数:将k个数据建立最小堆,每来一个数据都与根(最小值)比较,如果比根大,则替换根,做向下调整,找出新堆里面的最小值作为根,如此重复。
在数组中找最大值的方法

遍历一次
适合多次查找适合只找一次

向下调整

前提:对于一棵完全二叉树,除了一个位置以外,其他所有位置都满足堆的性质

   /*
    * 1.找到要调整的节点的最小孩子节点{1.无左孩子:不用调整
    *                               2.无右孩子:左孩子为最小孩子
    *                               3.左右孩子存在,选出最小 的}
    * 2.比较与根节点的大小{比根节点大:交换根节点与最小孩子的值,继续拿着最小孩子向下调整;
    *                   比根节点小:不用调整}
    * */
     //时间复杂度O(logn)
     
 private void adjustHeap(int[] tree, int index) {
        //找左孩子
        int min =2* index + 1;
       
        while (min < tree.length) {
            //找右孩子,取最小的
            if (min + 1 < tree.length && tree[min + 1] < tree[min]) {
                min = min + 1;
            }

            //与根比较
            if (tree[index] < tree[min]) {
                return;
            }
            int t = tree[min];
            tree[min] = tree[index];
            tree[index] = t;

            index = min;
            min = 2 * index + 1;


        }
    }

建堆:

    //时间复杂度O(n)
    //粗略nO(logn)
    public static void createHeap(int[] array){
        //从最后一个非叶子节点的下标开始,一路向下调整至根位置
        for(int i=(array.length-1-1)/2;i>=0;i--){
            heapify(array,i);
        }
    }
public class CreateHeap {
    private int[] array;
    private int size;

    public CreateHeap(int[] array, int size) {
        this.array = new int[100];
        for (int i = 0; i < size; i++) {
            this.array[i] = array[i];
        }
        this.size = size;
        getHeap(this.array, size);
    }

    private void getHeap(int[] array, int size) {
        //大堆,从非叶子节点开始建
        for(int i=(size-2)/2;i>=0;i--){
            heaplify2(array,i);
        }

    }

    private void heaplify(int[] array, int nowParent) {
        int max = nowParent * 2 + 1;
        if (max > size) {
            return;
        }
        if (max + 1 < size && array[max + 1] > array[max]) {
            max++;
        }
        //与根比较
        if (array[nowParent] > array[max]) {
            return;
        }

        //叶子比根大,调整
        int t = array[max];
        array[max] = array[nowParent];
        array[nowParent] = t;
        //继续向下调整
        heaplify(array, max);
    }
private static void heaplify2(int[] array,int index){

    while (index<array.length) {
        int max=index*2+1;
        if(max>array.length){
            break;
        }
        int right=index*2+2;
        if(right>array.length){
            break;
        }
        if(array[right]>array[max]){
            max=right;
        }


        if(array[max]<array[index]){
            break;
        }

        //做交换
        int t=array[index];
        array[index]=array[max];
        array[max]=t;

        index=max;

    }

}


    private int top() {
        return this.array[0];
    }

    private int pop() {
        int v = array[0];
        //将最后一个节点放到根节点上,再做堆的重建
        array[0] = array[this.size - 1];
        size--;
        getHeap(array, size);
        return v;
    }

    public static void adjustUP(int[] tree, int size, int index) {
        //建大堆
        //向上和双亲比较
        int parent = (index - 1) / 2;
        if (parent == 0) {
            return;
        }
        if (tree[index] <= tree[parent]) {
            return;
        }
        //向上调整,与双亲节点做交换
        int t = tree[index];
        tree[index] = tree[parent];
        tree[parent] = tree[index];
        //终止条件:
        adjustUP(tree, size, parent);
    }

    public static void adjustUP2(int[] tree, int size, int index) {
        while (index > 0) {
            int parent = (index - 1) / 2;
            if (tree[index] <= tree[parent]) {
                return;
            }
            int t = tree[index];
            tree[index] = tree[parent];
            tree[parent] = t;
            index = parent;
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值