C++ visualc&x2B+;只使用一个std::list实现std::无序_映射?

C++ visualc&x2B+;只使用一个std::list实现std::无序_映射?,c++,c++11,C++,C++11,我想实现一个类似于std的无序映射。因此,我在VisualC++ 2013中查看了源代码在 和 。我在无序映射构造函数中找到了实现调用\u Init函数。我发现函数的定义如下: void _Init(size_type _Buckets = _Min_buckets) { // initialize hash table with _Buckets buckets, leave list alone _Vec.assign(2 * _Buckets, _Unchecked_end()

我想实现一个类似于std的
无序映射。因此,我在VisualC++ 2013中查看了源代码在<代码> <代码>和<代码> <代码>。我在
无序映射
构造函数中找到了实现调用
\u Init
函数。我发现函数的定义如下:

void _Init(size_type _Buckets = _Min_buckets)
{   // initialize hash table with _Buckets buckets, leave list alone
    _Vec.assign(2 * _Buckets, _Unchecked_end());
    _Mask = _Buckets - 1;
    _Maxidx = _Buckets;
}         
函数
\u Unchecked\u end()
只返回
\u列表。Unchecked\u end()

std::unordered\u映射的
begin()
只返回
\u List.begin()

我认为只有一个列表的
unordered_map
函数的
find()

所以。。。VC++究竟是如何实现std::无序映射的


对不起,我没说清楚。我认为,
unordered_-map
的实现应该是一个包含多个列表的向量(Init包含不同的不同的
std::list
s的不同迭代器)。但是我只找到一个列表(Init的迭代器为one
std::list
)。这就是问题所在。

哈希表的教科书式实现就是你所说的:排序为列表数组,每个“bucket”一个列表

但是如果你仔细想想,就没有必要有一大堆单独的列表——你可以只有一个!这可能会提高顺序访问性能(注意,它是无序的,但您仍然可以为哈希表中的“每个”元素执行操作)

因此,想象一下使用一个链表:将所有值放在其中,对于数组(向量),使用指针/迭代器直接进入一个链表。如果你想知道一个桶从哪里开始,这和教科书上的解决方案是一样的。要知道一个存储桶的结束位置,只需查看下一个存储桶的开始位置(在固定时间内)

从另一个角度来看,这是一个教科书式的实现,有一个修改:每个bucket末尾的“next”指针指向以下非空bucket的开头。您将立即看到为什么这会改进顺序访问——它消除了遍历空存储桶的成本(其中可能有负载,因为实现不需要收缩哈希表,只需要增加它)


有趣的故事:缺乏这类技巧是导致GCC和Boost无序_映射多年来具有线性而非恒定时间
擦除(迭代器)
性能的部分原因。有关GCC,请参阅。有关Boost,请参见。

哈希表的教科书实现,如您所说:排序为列表数组,每个“bucket”一个列表

但是如果你仔细想想,就没有必要有一大堆单独的列表——你可以只有一个!这可能会提高顺序访问性能(注意,它是无序的,但您仍然可以为哈希表中的“每个”元素执行操作)

因此,想象一下使用一个链表:将所有值放在其中,对于数组(向量),使用指针/迭代器直接进入一个链表。如果你想知道一个桶从哪里开始,这和教科书上的解决方案是一样的。要知道一个存储桶的结束位置,只需查看下一个存储桶的开始位置(在固定时间内)

从另一个角度来看,这是一个教科书式的实现,有一个修改:每个bucket末尾的“next”指针指向以下非空bucket的开头。您将立即看到为什么这会改进顺序访问——它消除了遍历空存储桶的成本(其中可能有负载,因为实现不需要收缩哈希表,只需要增加它)


有趣的故事:缺乏这类技巧是导致GCC和Boost无序_映射多年来具有线性而非恒定时间
擦除(迭代器)
性能的部分原因。有关GCC,请参阅。有关Boost,请参见。

什么是“只有一个列表”?您正在抱怨
std::list
std::unordered_map
具有不同的访问复杂性;你知道它们是不同的数据结构吗?如果你想实现你自己的
无序映射
,首先阅读,了解它的所有内容,了解它背后的概念(哈希和哈希表),然后不要阅读高度优化的标准库中的任何实现。这些标准库并不容易阅读和理解,但是如果您了解哈希表背后的概念,那么您可以轻松地构建自己的实现。
\u Vec
是描述每个bucket的迭代器向量(进入
\u List
)。所有的bucket都链接在一个链表中,但每个bucket都可以在固定时间内访问,这很好。“只有一个列表”是什么意思?您正在抱怨
std::list
std::unordered_map
具有不同的访问复杂性;你知道它们是不同的数据结构吗?如果你想实现你自己的
无序映射
,首先阅读,了解它的所有内容,了解它背后的概念(哈希和哈希表),然后不要阅读高度优化的标准库中的任何实现。这些标准库并不容易阅读和理解,但是如果您了解哈希表背后的概念,那么您可以轻松地构建自己的实现。
\u Vec
是描述每个bucket的迭代器向量(进入
\u List
)。所有的bucket都链接到一个链表中,但每个bucket都可以在固定时间内访问。这也使得迭代器的实现变得微不足道。@T.C.:的确,请看我添加的“有趣的故事”,我想这就是迭代器实现起来并不微不足道时的情况。:)这也使得迭代器的实现变得微不足道。@T.C.:的确,请看我添加的“有趣的故事”,T
_Unchecked_iterator _Unchecked_end()
{   // return iterator for end of mutable sequence
    return (_List._Unchecked_end());
}