top-k查询解决方案

时间:2011-12-21 18:48:58

标签: c++ algorithm

有没有人有解决top-k查询问题的方法。 问题是我有无限数量的流,我需要提出解决方案,这将给我流中的前k项。

这是面试问题。我正在寻找C ++解决方案。

这是我将如何解决问题。但在这里,我需要阅读整个stream/file

#include <iostream>
#include <fstream>
#include <string>
#include <map>

typedef std::map<std::string, int> freq_table_t;
typedef std::multimap<std::size_t, freq_table_t::const_iterator> top_n_t;
size_t n = 5;

int main ( int argc, char **argv) {
    std::ifstream ifs(argv[1]);
    if ( ifs.peek() == EOF )
        return 1;

    std::string line;
    freq_table_t freq_table;

    while( ifs.good()&& std::getline(ifs,line) ) {
        if ( freq_table.insert(std::make_pair(line, 1 )).second == false )
            freq_table[line]++;
    }
    ifs.close();

    top_n_t top5;
    for (freq_table_t::const_iterator it = freq_table.begin(); it != freq_table.end(); ++it) {
        if (top5.size() < n || it->second > top5.begin()->first)
            top5.insert(std::make_pair(it->second, it));
        if (top5.size() == n + 1)
            top5.erase(top5.begin());
    }
    for ( top_n_t::reverse_iterator ritr = top5.rbegin(); ritr != top5.rend(); ++ritr)
        std::cout << ritr->second->first << std::endl;

    return 0;
}

2 个答案:

答案 0 :(得分:3)

  • 创建std::set<int> top
  • 对于您从流中获得的每个号码:
  • - 将号码添加到集合
  • - 如果top.size() > k,请删除该组中的最小元素。

在每个点,top最多包含k个项目中的最大项目(如果项目中的k个项目少于k,则该数字将小于{{1}}直到这一点的流)。 用C ++编写代码应该是微不足道的。

答案 1 :(得分:1)

推广dasblinkenlight的回答:

维持最小优先级队列。对于流中的每个元素,将元素与队列中的最小元素进行比较。如果它更大,则将最小元素出列并将新元素排入队列。作为基本情况,将队列初始化为流的第一个k元素。

在流的末尾,您的优先级队列将包含最大的k元素。

根据流中的n元素,此算法将在n log k时间内运行。