使用C++优先队列(priority_queue)解决Top K问题

背景

在同构的n个数据中取Top K的最大值或者最小值有很多方法,例如:

  • 排序后,取前K个或者后K个,算法复杂度为nlog(n);
  • 维护大小为K的最大(小)堆,最后取堆中的元素,算法 复杂度为nlog(k)。
    当n很大时,第二种方法可以得到显著的速度提升。本文以C++保准库提供的priotiry_queue为基础,实现基于堆的Top K算法。

步骤

  1. 创建有限队列
//自定义结构的比较器,这里为优先级队列实现一个Great比较器,使优先级队列元素从小到大跑得了排序
struct cmpPairSecondFloatGreat{
    bool operator() (const std::pair<int32_t, float>&a, const std::pair<int32_t, float>& b) {
        return a.second > b.second;
    }
};
//定义优先级队列,队列实现最小堆,即top为最小值。
std::priority_queue<std::pair<int32_t, float>, std::vector<std::pair<int32_t, float>>, cmpPairSecondFloatGreat> noise_words;

以取最大Top K为例,将自定义比较器给优先级队列。

  1. 更新优先级队列中的值
for (int i = 0; i < 100000000; i++) {
    float num = float(rand());
    if (pq.size() < 3){ //以Top 3为例
      pq.push(make_pair(0, num));
    } else {
      if( num < pq.top().second) {
        continue;
      } else {
        pq.pop(); // 如果当前值比待插入值大,则将队头元素删除,将当前值插入队列中。
        pq.push(make_pair(1, num));
      }
    }
    vecs.push_back(make_pair(0, num));
  }
  1. 获取Top K的值
    取出有限队列中的值,即得到Top K的值。
while (!pq.empty()) {
    cout << pq.top().second << " ";
    pq.pop();
  }

总结

通过有限队列内部实现的堆算法,手动控制有限队列的大小,即可模拟实现基于最大(小)堆的Top K算法。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 优先队列的数据结构支持两种操作:删除最大元素和插入元素优先队列的使用和队列(删除最老的元素)以及栈(删除最新的元素...
    RoyTien阅读 1,566评论 0 1
  • top-K问题指的是从一个数组中找出里面前k大或是前k小的问题。解决这类问题可以有以下的集中方法。 1、排序。排序...
    道禅_26ea阅读 1,996评论 0 1
  • 前言 今日份的内容很简单,看官可以放心食用。 二叉堆 这一部分完全是大学数据结构课程的复习。 性质 顾名思义,二叉...
    LittleMagic阅读 1,925评论 4 12
  • 概述 因为健忘,加上对各种排序算法理解不深刻,过段时间面对排序就蒙了。所以决定对我们常见的这几种排序算法进行统一总...
    清风之心阅读 722评论 0 1
  • 夜已深,重温一遍「阿甘正传」,感触太多了。我们常说:懂得很多道理,依然过不好这一生。可是像阿甘、许三多这样的人,都...
    1fd39acb7902阅读 469评论 0 4