我需要一个满足以下用例的数据结构:
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()
属性的副本)。
这些数据存储区的行为是预先进行的批量加载,偶尔会在对象的整个生命周期内进行,但会不断提取内容。因此,任何在前端都很重要的数据结构都可以工作。
思想?
答案 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
迭代器。