我有一个问题,我有大量的数字对。类似的东西:
(0, 1)
(10, 5)
(5, 6)
(8, 6)
(7, 5)
.....
我需要做的是,如果列表中存在对,我可以进行非常快速的查找。
我的第一个想法是make map< std::pair<int,int> >
容器。并使用container.find()
进行搜索。
第二个想法是通过使用vector<vector<int>
使我可以搜索的std::find(container[id1].begin(),container[id1].end(),id2)
容器成对存在;
第二种方式比第一种方式快一点,但如果可能的话,我需要更有效的方法。
所以问题是有更有效的方法来查找列表中是否存在数字对?
启动程序时我知道的对数,所以我不太关心对插入/删除,我只需要非常快速的搜索。
答案 0 :(得分:4)
如果您不关心插入,可以使用已排序的std :: vector和std :: binary_search,或std :: lower_bound。
int main()
{
using namespace std;
vector<pair<int, int>> pairs;
pairs.push_back(make_pair(1, 1));
pairs.push_back(make_pair(3, 1));
pairs.push_back(make_pair(3, 2));
pairs.push_back(make_pair(4, 1));
auto compare = [](const pair<int, int>& lh, const pair<int, int>& rh)
{
return lh.first != rh.first ?
lh.first < rh.first : lh.second < rh.second;
};
sort(begin(pairs), end(pairs), compare);
auto lookup = make_pair(3, 1);
bool has31 = binary_search(begin(pairs), end(pairs), lookup, compare);
auto iter31 = lower_bound(begin(pairs), end(pairs), lookup, compare);
if (iter31 != end(pairs) && *iter31 == lookup)
cout << iter31->first << "; " << iter31->second << "at position "
<< distance(begin(pairs), iter31);
}
答案 1 :(得分:2)
std::set
可能是要走的路,即使元素数量增加,它也应该表现得相当好(而std::vector
的性能会很快减慢,除非你事先对它进行排序某种二进制或树搜索)。请注意,您必须定义<
运算符才能使用std::set
。
如果您可以使用c ++ 0x,std::unordered_set
也值得一试,特别是如果您不关心订单。你会在Boost中找到unordered_set
。这不需要定义<
运算符。如果你使unordered_set
具有合适的大小并定义自己的简单散列函数,它不会产生很多碰撞,那么它甚至可能比对有序向量的二进制搜索更快。
答案 2 :(得分:2)
如果您想要快于设置的查找(比O(lg n)
更快)并且不关心项目是否是随机顺序,那么哈希表是可行的方法。
这不是标准的一部分,但大多数编译器都可以使用hash_set
。它的参考是here。
如果您希望真正快速搜索,可以尝试Bloom filter。然而,它们有时会导致误报(即,当没有物品对时检测到物品对),并且需要大量记忆。一个合适的Bloom过滤器实现将是:
const int MAX_HASH = 23879519; // note it's prime; must be 2-5 times larger than number of your pairs
vector<bool> Bloom(MAX_HASH); // vector<bool> compresses bools into bits
// multiply one by a large-ish prime, add the second, return modulo another prime
// then use it as the key for the filter
int hash(long long a, long long b) {
return (a*15485863LL + b) % MAX_HASH;
}
// constant-time addition
void add_item(pair<int,int> p) {
Bloom[hash(p.first, p.second)] = true;
}
// constant-time check
bool is_in_set(pair<int,int> p) {
return Bloom[hash(p.first, p.second)];
}
答案 3 :(得分:1)
您可以使用hash_set的一些实现来加快速度 例如boost :: unordered_set,其中键是std :: pair。 这是最简单方法中最快的。
答案 4 :(得分:1)
如果你的个人数字是int
,那么这是另一个解决方案。
long long
构造int
(第一个int
可以是高32位,第二个int
是低32位)unorderd_set
(或set
或已排序的vector
- 个人资料中以查找您的匹配项)应该比使用对/元组等更快一些百分比。尤其是。
答案 5 :(得分:-1)
为什么不按照第一个元素排序元组,然后是第二个元素,然后二元搜索应该是O(log(n))。