JAVA中的堆

2 篇文章 0 订阅

1.堆

堆实际上就是用数组将一个完全二叉树存起来,堆的主要用途就是用来找集合中的最大值和最小值,也可以解决top-K问题,就是类似找出第一最大值,第二最大值。。。。

1》堆可以分为:大堆和小堆
大堆:树中的任意节点,节点值必须大于左右孩子的值
小堆:树中的任意节点,节点值必须小于左右孩子的值

2》堆的调整操作:
向上调整(除根结点外,其他结点都符合堆的要求)对象:大堆小堆

private   void shiftUp(int[] array,int size,int index) {
        int child = index;
        int parent = (child-1)/2;
        while (child > 0) {
            if (array[parent]<array[child]) {
                int tmp = array[parent];
                array[parent] = array[child];
                array[child] = tmp;
            }else {
                break;
            }
            child = parent;
            parent = (child-1)/2;


        }
    }

时间复杂度:O(logN)
向下调整(除孩子结点,其他结点都符合堆的要求)对象:大堆小堆

 public static void shiftDown(int[] array,int size,int index) {
        int parent = index;
        int child = 2*parent+1;
        while (child<size) {
            if (child+1<size&&array[child+1]>array[child]) {
                child = child+1;
            }
            if (array[child]>array[parent]) {
                int tmp = array[child];
                array[child] = array[parent];
                array[parent] = tmp;
            }else {
                break;
            }
            parent = child;
            child = 2*parent+1;
        }
    }

时间复杂度:O(logN)

3》建堆(时间复杂度:O(N))
基于向下调整建堆必须从后往前遍历数组
基于向上调整建堆必须从前往后遍历数组

   public static void createHeap(int[] array,int size) {
        for (int i = (size-1-1)/2;i>=0;i--) {
            shiftDown(array,size,i);
        }
    }

2.用堆创建的优先队列

1》入队列

 public void offer(int x) {
        array[size] = x;
        size++;
        shiftUp(array,size,size-1);
    }

直接插到数组最后,然后向上调整成大堆

2》出队列

public Integer poll() {
        if (size <= 0) {
            return null;
        }
        int ret = array[0];
        array[0] = array[size-1];
        size--;
        shiftDown(array,size,0);
        return ret;
    }

即将数组第一个元素取出并删除还要保持剩下的结点是一个堆,用新的变量保存根节点,然后将最后一个元素赋值给第一个,然后size–将最后一个元素删除,在从0号元素进行向下调整就可以保证剩下元素是堆,然后返回新的变量,最大值就取到了。

3》取队首元素

public Integer peek() {
        if (size == 0) {
            return null;
        }
        return array[0];
    }

3.标准库中的优先队列

import java.util.Comparator;
import java.util.PriorityQueue;


// 标准库中的优先队列默认为小堆

public class TestPriorityQueue {
//自定义优先级
    static class MyComp implements Comparator<Integer> {
        public int compare(Integer o1,Integer o2) {

            return o2-o1;
        }
    }
    public static void main(String[] args) {
        PriorityQueue<Integer> queue = new PriorityQueue<>(new MyComp());
        queue.offer(9);
        queue.offer(5);
        queue.offer(2);
        queue.offer(7);
        queue.offer(3);
        queue.offer(6);
        queue.offer(8);
        while (!queue.isEmpty()) {
            Integer cur = queue.poll();
            System.out.println(cur);
        }

    }
}

标准库中的优先队列默认是小堆,即最小的优先权最高,我们可以通过定义这个比较器来修改输出顺序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhj_loveFang_1105

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值