存储需要精确且最接近匹配的值的最佳结构

时间:2015-02-09 11:15:22

标签: c++ c++11 dictionary vector

我需要一个满足以下用例的数据结构:

  1. 按键存储项目
  2. 按键检索确切值的功能
  3. 按键检索最接近的先前值的功能
  4. 按键检索最接近的后续值的功能
  5. 1和2是显而易见的。对于3(和4),假设密钥是自定义Date对象,最接近的先前值,例如2014年12月1日的搜索,将返回具有最接近2014年12月1日的日期的值。因此,如果先前值具有11月10日,11日,14日,15日和29日的密钥,然后它将返回11月29日。对于4,功能是相同的,但是最接近的日期将在12月1日之后。

    目前我正在使用std::map<Date, T>,但3和4的要求是新的。我考虑过的事情:

    • 继续使用std::map<Date, T>(log-n商店和精确检索。最接近的匹配将是蛮力的,因此在速度方面约为n)
    • 使用std::vector<T>,使用我自己的排序例程(常量存储,log-n检索精确和最接近;我可以滚动我自己的获取例程并通过索引访问std::vector<T>的成员以获得快速二分搜索)

    我倾向于std::vector<T>,因为我的T对象内置了Date(出于std::map<Date, T>的目的,Date只是T.date()属性的副本)。

    这些数据存储区的行为是预先进行的批量加载,偶尔会在对象的整个生命周期内进行,但会不断提取内容。因此,任何在前端都很重要的数据结构都可以工作。

    思想?

2 个答案:

答案 0 :(得分:1)

地图中的元素已排序。 如果你的Date对象有适当的比较运算符(或你的地图有一个),你可以使用map :: find来获取你的对象迭代器,然后向前和向后移动迭代器(强制转换为reverse_iterator)以获得最接近的值。

如果元素不在容器中,你应该看看: STL "closest" method?

答案 1 :(得分:0)

这就是我解决它的方法:

#include <map>
#include <iostream>
#include <string>
#include <iterator> // for std::prev

using namespace std; // for brevity

void test(const map<int,string>& data, int key)
{
    cout << "searching for " << key << endl;

    auto range = data.equal_range(key);
    auto it1 = range.first;
    auto it2 = range.second;

    if (it1 != it2)
        cout << "\tfound: " << it1->second << endl;

    auto closestPrior = (it1 != data.begin()) ? prev(it1) : data.end();
    auto closestAfter = it2;

    if (closestPrior != data.end())
        cout << "\tprior: " << closestPrior->second << endl;
    if (closestAfter != data.end())
        cout << "\tafter: " << closestAfter->second << endl;
}

int main()
{
    map<int, string> data;
    data[1] = "one";
    data[5] = "five";
    data[9] = "nine";

    for (int i=0; i<11; ++i)
        test(data, i);
}

我使用.equal_range()而不是同时调用.lower_bound().upper_bound()。唯一的特殊处理是下限是begin迭代器。

See it live