java大顶堆小顶堆

一,堆的介绍和常见用法

堆又可称之为完全二叉堆。这是一个逻辑上基于完全二叉树、物理上一般基于线性数据结构(如数组、向量、链表等)的一种数据结构。
堆又分成大根堆和小根堆。大根堆即根节点大于叶子节点,下面的父节点也比孩子节点大。小根堆与之相反即根节点小于叶子节点,下面的父节点也比孩子节点小。
根堆的最常见的用法是获取数组的topN个数据。比如可以通过大根堆来得到数组中topK小的数据,或者小根堆获取数组中topk大的数据。
以大根堆来得到数组中topK小的数据来讲解,数组中前k个数据直接进堆构造成量级为k的大根堆,对于k个之后的数据,进堆前要判断是不是比堆顶元素要小,如果不是就不动,如果比堆顶小就把堆顶元素弹出然后数据进堆(堆会重构成大根堆),这样就相当于把堆中的最大数替换成较小的值了。这样一直替换下去最后堆中保存的就是数组topk个最小值了。
相似的数组中topk最大值通过小根堆来操作,原理一样。

二,Java中堆的使用

Java中堆是PriorityQueue 实现的。Java PriorityQueue实现了Queue 接口,不允许放入 null 元素。
默认是小根堆,要定义大根堆的话需要在定义式实现comparator类,重写compare函数。
常用方法总结:

public boolean add(E e); //在队尾插入元素,插入失败时抛出异常,并调整堆结构
public boolean offer(E e); //在队尾插入元素,插入失败时抛出false,并调整堆结构
public E remove(); //获取队头元素并删除,并返回,失败时前者抛出异常,再调整堆结构
public E poll(); //获取队头元素并删除,并返回,失败时前者抛出null,再调整堆结构
public E element(); //返回队头元素(不删除),失败时前者抛出异常
public E peek();//返回队头元素(不删除),失败时前者抛出null
public boolean isEmpty(); //判断队列是否为空
public int size(); //获取队列中元素个数
public void clear(); //清空队列
public boolean contains(Object o); //判断队列中是否包含指定元素(从队头到队尾遍历)
public Iterator<E> iterator(); //迭代器

TopK的问题:

public int[] inventoryManagement(int[] stock, int cnt) {
    //使用大根堆来获取topk的最小值,大根堆即根节点大于叶子节点,构造完之后每次数据与堆顶元素相比比堆顶大就进堆。
    //这样就把堆中最大元素替换成了较小值,这样最后堆中存储的就是k个最小值了。
    int[] res = new int[cnt];
    if(cnt==0)
        return res;
    //构造大根堆,实现compare函数。    
    PriorityQueue<Integer> pqueue = new PriorityQueue<Integer>(new Comparator<Integer>() {
        public int compare(Integer num1,Integer num2){
            return num2 - num1;
        }
    });
    for(int i=0;i<stock.length;i++){
        if(i<cnt)
            pqueue.offer(stock[i]);
        else{
            int topnum = pqueue.peek();
            if(stock[i] < topnum){
                pqueue.poll();
                pqueue.offer(stock[i]);
            }
        }
    }
    for(int i=0;i<cnt;i++){
        res[i] = pqueue.poll();            
    }
    return res;
}
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一杯拿铁go

你的打赏是我更新最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值