equal_range和std :: unordered_multiset

时间:2014-12-22 16:13:26

标签: c++ c++11 stl

我的理解是我们不能对无序...容器中的元素顺序做出任何假设(即使它们是通过哈希表实现的)。如果这是正确的,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

2 个答案:

答案 0 :(得分:5)

该标准规定了[unord.req] / 6中<= p>的范围内相等元素的位置

  

在支持等效键的容器中,元素具有等效键   密钥以迭代顺序彼此相邻   容器即可。因此,虽然元素的绝对顺序在   未指定无序容器,其元素被分组   等效键组,使得每个组的所有元素都具有   等效键。无序容器的变异操作应   保留每个等效键中元素的相对顺序   除非另有说明,否则小组。

答案 1 :(得分:5)

来自cplusplus.com

  

具有等效值的元素在同一个桶中组合在一起,并且迭代器(参见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; =

这完全基于规范,实施仍然开放。 由于问题是“如何”,可能的方式是

  1. 使用给定的hash_code
  2. 获取存储桶中的元素
  3. 启动过滤元素,使用运算符&lt; =
  4. 丢弃不需要的元素

    unordered_multiset的智能实现将以某种方式“pre_filter”元素,以便调用“equal_range”便宜。但实现不需要那么聪明,并且在调用“range_equals”时可能会产生性能问题(假设你的hash_function不是很聪明)