我的理解是我们不能对无序...容器中的元素顺序做出任何假设(即使它们是通过哈希表实现的)。如果这是正确的,std :: unordered_multiset :: equal_range()如何返回一系列相等的值?
例如:
typedef std::unordered_multiset<int> int_set;
typedef int_set::iterator int_set_iterator;
int_set set;
set.insert(1);
set.insert(2);
set.insert(1);
set.insert(3);
set.insert(1);
// equal_range seems to assume all 1s are located next to each other
std::pair<int_set_iterator, int_set_iterator> range = set.equal_range(1);
size_t range_size = std::distance(range.first, range.second); // the value is 3
答案 0 :(得分:5)
该标准规定了[unord.req] / 6中<= p>的范围内相等元素的位置
在支持等效键的容器中,元素具有等效键 密钥以迭代顺序彼此相邻 容器即可。因此,虽然元素的绝对顺序在 未指定无序容器,其元素被分组 等效键组,使得每个组的所有元素都具有 等效键。无序容器的变异操作应 保留每个等效键中元素的相对顺序 除非另有说明,否则小组。
答案 1 :(得分:5)
具有等效值的元素在同一个桶中组合在一起,并且迭代器(参见equal_range)可以遍历所有这些元素。
从标准:
unordered_multiset :: equal_range :成员函数返回一个范围,其中包含具有指定键的所有元素。如果不存在这样的元素,它返回make_pair(end(),end())
了解另见equal_range:
因此,该函数确定了可以在序列中插入val的最大位置范围,并且仍然保留其排序。
没有关于如何保留此顺序的任务。
如果相同的元素具有相同的键和值,则不指定相等的元素需要是连续的。相同的密钥可能意味着具有相同散列的元素可以被分组为gheter(等效意味着相同的散列),实际上以下测试提供了一个示例,其中不同的元素按键分组(由于覆盖的hash_function,所有都具有密钥1),但代码是仍然正常工作。
#include <iostream>
#include <unordered_set>
using namespace std;
template <typename T>
struct my_hash
{
size_t operator()(const T k) const
{
// Compute individual hash values for two data members and combine them using XOR and bit shifting
return 1;
}
};
int main() {
typedef std::unordered_multiset<int,my_hash<int> > int_set;
typedef int_set::iterator int_set_iterator;
int_set set;
set.insert(1);
set.insert(2);
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(1);
// equal_range seems to assume all 1s are located next to each other
std::pair<int_set_iterator, int_set_iterator> range = set.equal_range(1);
size_t range_size = std::distance(range.first, range.second);
std::cout<<range_size<<std::endl; // print 3
range = set.equal_range(2);
range_size = std::distance(range.first, range.second);
std::cout<<range_size<<std::endl; //print 2
range = set.equal_range(3);
range_size = std::distance(range.first, range.second);
std::cout<<range_size<<std::endl; //print 1
return 0;
}
简而言之,unordered_multiset上的equal_range会生成一个由key(哈希值)首先选择的值的“列表”,然后,这些值被“过滤”,以便它们是等价的并且(根据equal_range规范)排序由运营商&lt; =
这完全基于规范,实施仍然开放。 由于问题是“如何”,可能的方式是
unordered_multiset的智能实现将以某种方式“pre_filter”元素,以便调用“equal_range”便宜。但实现不需要那么聪明,并且在调用“range_equals”时可能会产生性能问题(假设你的hash_function不是很聪明)