美文网首页
TopK及小根堆

TopK及小根堆

作者: 培根好吃 | 来源:发表于2018-08-22 19:52 被阅读0次
public class MinHeap
{
    // 堆的存储结构 - 数组
    private int[] data;
    
    // 将一个数组传入构造方法,并转换成一个小根堆
    public MinHeap(int[] data)
    {
        this.data = data;
        buildHeap();
    }
    
    // 将数组转换成最小堆
    private void buildHeap()
    {
        // 完全二叉树只有数组下标小于或等于 (data.length) / 2 - 1 的元素有孩子结点,遍历这些结点。
        // *比如上面的图中,数组有10个元素, (data.length) / 2 - 1的值为4,a[4]有孩子结点,但a[5]没有*
        for (int i = (data.length) / 2 - 1; i >= 0; i--) 
        {
            // 对有孩子结点的元素heapify
            heapify(i);
        }
    }
    
    private void heapify(int i)
    {
        // 获取左右结点的数组下标
        int l = left(i);  
        int r = right(i);
        
        // 这是一个临时变量,表示 跟结点、左结点、右结点中最小的值的结点的下标
        int smallest = i;
        
        // 存在左结点,且左结点的值小于根结点的值
        if (l < data.length && data[l] < data[i])  
            smallest = l;  
        
        // 存在右结点,且右结点的值小于以上比较的较小值
        if (r < data.length && data[r] < data[smallest])  
            smallest = r;  
        
        // 左右结点的值都大于根节点,直接return,不做任何操作
        if (i == smallest)  
            return;  
        
        // 交换根节点和左右结点中最小的那个值,把根节点的值替换下去
        swap(i, smallest);
        
        // 由于替换后左右子树会被影响,所以要对受影响的子树再进行heapify
        heapify(smallest);
    }
    
    // 获取右结点的数组下标
    private int right(int i)
    {  
        return (i + 1) << 1;  
    }   
 
    // 获取左结点的数组下标
    private int left(int i) 
    {  
        return ((i + 1) << 1) - 1;  
    }
    
    // 交换元素位置
    private void swap(int i, int j) 
    {  
        int tmp = data[i];  
        data[i] = data[j];  
        data[j] = tmp;  
    }
    
    // 获取对中的最小的元素,根元素
    public int getRoot()
    {
            return data[0];
    }
 
    // 替换根元素,并重新heapify
    public void setRoot(int root)
    {
        data[0] = root;
        heapify(0);
    }
}
public class TopK
{
    public static void main(String[] args)
    {
        // 源数据
        int[] data = {56,275,12,6,45,478,41,1236,456,12,546,45};
        
// 获取Top5
        int[] top5 = topK(data, 5);
        
        for(int i=0;i<5;i++)
        {
            System.out.println(top5[i]);
        }
    }
    
    // 从data数组中获取最大的k个数
    private static int[] topK(int[] data,int k)
    {
        // 先取K个元素放入一个数组topk中
        int[] topk = new int[k]; 
        for(int i = 0;i< k;i++)
        {
            topk[i] = data[i];
        }
        
        // 转换成最小堆
        MinHeap heap = new MinHeap(topk);
        
        // 从k开始,遍历data
        for(int i= k;i<data.length;i++)
        {
            int root = heap.getRoot();
            
            // 当数据大于堆中最小的数(根节点)时,替换堆中的根节点,再转换成堆
            if(data[i] > root)
            {
                heap.setRoot(data[i]);
            }
        }
        
        return topk;
}
}

相关文章

  • TopK及小根堆

  • incr+zadd+小根堆,实现简易topK榜单

    很容易想到使用redis的zset来做。为了能保证用户分数安全的并发累加,配合使用incr操作(每个贡献用户占一个...

  • TOPK 问题

    TOPK 问题 描述 如从海量数字中寻找最大的 k 个,这类问题我们称为 TOPK 问题,通常使用堆来解决: 求前...

  • 二叉树的应用

    1 排序二叉树和堆 用途树结构关系存储方式应用(大根)堆排序完全二叉树根>左子树,根>右子树数组堆排序,取topk...

  • 堆的创建

    二叉堆的定义 堆通常由大根堆和小根堆,大根堆表示父节点大于字节点,小根堆相反eg:小根堆 可以看出堆屎一个完全二叉...

  • 2018-08-14 LeetCode数据流的中位数

    较小的一半数放在大根堆较大的在小根堆,大根堆堆顶为较小数的最大值,小根堆的堆顶为较大数的最小值始终保持大根堆和小根...

  • 数据结构与算法之堆排序

    小根堆--向下构建 大根堆--向上构建 不要误解,其实无论向上调整还是向下调整都是可以构建大根堆或者小根堆的。注:...

  • 14_堆TopK排序

  • 堆简述 堆(heap)的结构是一个完全二叉树的结构。 堆分大根堆和小根堆。如果一个二叉树它即不是大根堆,也不是小根...

  • 春招笔记 堆

    1. 堆是完全二叉树,根据父节点和子节点的关系,可以分为大根堆和小根堆。 大根堆的父节点比它的所有子节点大,小根...

网友评论

      本文标题:TopK及小根堆

      本文链接:https://www.haomeiwen.com/subject/uutuiftx.html