C++ unordered Associative Containers(C++11)

C++11 引进了无序关联容器(unordered associative containers)的概念。 有unordered set or multiset, 以及unordered map or multimap。

顾名思义, unordered的意思就是元素没有固定的顺序, 并且元素的顺序可能会随着时间的变化而变化。

Internally, unordered container 是使用hash table(哈希表)实现的。 所谓的hash Table, 就是an array of linked list. 整个数组又被称为an array of buckets。

那些linked lsit 被称为entries。

每一个元素作为一个hash function的输入参数,  hash function 输出这个元素对应的hash value(哈希值)。 然后根据这个值将这个元素添加到对应的linked list 的合适的位置。

上述结构的优点就是, 当你有一个fast and effective function , finding an element in the hash table is very fast, 花费的时间是常数时间O(1). 这是所有的容器中最快的一种。

例如下图, 创键了一个unordered set (无序集合)of string, 名字为myset(存储着red, green, blue);

然后使用set的成员函数find()去查找myset 中的green,  这一步仅仅需要花费常数时间(O(1))非常之快。 如果找到了这个元素, 该函数会返回指向这个元素的迭代器, 如果没有找到这个元素, 那么该函数会返回一个指向the end of the container 的迭代器, 所以我们需要Check 是否找到了。 所以如下验证。 如果返回的是一个未定义的, 说明指向容器末尾, 也就是没有找到;

然后我们想这个无序set 中插入一个yellow, 这个操作也仅仅需要花费O(1);

我们也可以实用另外一个容器作为insert 的参数, 例如向量容器vec, myset 调用insert成员函数的时候, 可以将这个容器的所有元素都插入到无序容器myset中, 非常有效。

无序集合也为我们提供了hash Table的API,

load_factor() 是给出元素的总数与bucket的总数的比值。

函数bucket告诉我们我们的元素存储在那个bucket 之中。

bucket_count 告诉我们容器中有多少个bucket。

unordered multiset 允许我们的容器具有duplicated elements:

unodered map 非常想unordereded set, 区别就是unordered 的元素是有一组key 和value组成。

unordered multimap 允许duplicated keys。

我们需要记住的一点就是, 尽管hash Table 允许amortized constant time search, 但是这个性能会随着hash collision(哈希碰撞)而退化(降低)。

Q: 什么是hash collision:

A: 许多的元素被插入到同一个bucket中。

最坏的情况下, 当所有的元素被插入到一个bucket 的时候, 性能最差, 此时搜索所需要的时间变为了O(n):

无序容器的属性如下:

注意一点, 对于unordered set/multiset, 元素的值是不能够改变的, 因为改变值的时候, 将会改变其的data structures。也就是改变了hash table。

对于unordered map/multimap, 元素的key 也是不能随便改变的。 原因同上, 即会改变我们的hash table。

尽管STL中, 没有容器被称为关联数组(associative array), 但是我们仍然可以通过map 和unordered map 去实现它。

例如下面, 我们创建了一个unordereded map称为day, 存储的内容如下。

接下来, 存取相关的值就相当于存取数组的元素一样(通过索引, 只不过这里是key)。 注意用[] 存取无range Check, 用成员函数at 有range check。

需要注意的一点就是, 如果是向量, 如下, 使用vec[5]就会出错, 因为vec[5]并没有被创建(vec 只有三个元素)。

然而, 对于关联容器, 指令day[‘W ‘ ] = "Wednesday"会将{“W”, “Wednesday”}插入到关联容器中。 当然我们也可以调用insert函数。

然而, insert函数不能用于修改已经存在的元素值。 然而下标法却可以实现修改。 因为此时将其视为关联数组。

对于如下函数:

参数是pass by reference(const)。

在函数中, 我们修改了m, 所以下面的函数也不会通过编译。 因为m is not modifiable。

在看下面的函数, 假如我们只是打印出来, 那么会打印出来吗?

正确的答案是下面也不会通过编译, 出现的错误信息和上面的出现的错误信息是一样的。  原因是什么呢?

因为下标法[] 对我们的容器的操作是写操作。 所以当编译器看到m[‘S‘], 会assume you will write to the conatiners

所以, 为了实现读操作, 我们采用如下方式:

关于associative array, 我们有一下几点需要注意:

既然associative array 既可以用unordered map实现, 有可以用map 实现, 那么我们该使用哪一个呢?

不难看出, 对于搜索操作, unordered map 需要O(1)时间。 对于map, 需要花费O(log(n)), 表面上看, 似乎unordered map 占优。 但是我们应该知道map的时间是guaranteed, 而unordered map 当退化的时候, 花费的时间变成了线性的了。

还有一点就是, 我们不能使用multimap 和 unordered multimap去实现关联数组, 因为这两个容器的key 不是unique 的。而且二者还没有[]运算符。

STL也提供了三个容器适配器, 如下:

关于容器, 还有另外的一个分类方法:

上面的程序中, 输出的结果是未定义的。 每当插入或者删除基于数组的容器的元素, 以前指向某个元素的指针的可能无效了(invalidate)。

C++ unordered Associative Containers(C++11)

时间: 2024-10-06 06:14:57

C++ unordered Associative Containers(C++11)的相关文章

关联式容器(associative containers)

根据数据在容器中的排列特性,容器可分为序列式(sequence)和关联式(associative)两种. 标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及两大类的衍生体multiset(多键集合)和multimap(多键映射表).这些容器的底层机制均是以RB-tree(红黑树)完成.RB-tree也是一个独立的容器,但并不开放给外界使用. 此外,SGI STL还提供一个不在规格标准之列的关联式容器:hash table(散列表),以及以此hash table为底层机制而完成

Associative Containers

Notes from C++ Primer Associative containers differ in fundamental respect from the sequential containers: elements in associative containers are stored and retrieved by a key, in contrast to elements in a sequential container, which are stored and a

chapter 16

Chapter 16 # string class Constructors (Page 952) string(const char *s) string(size_type n, char c) string(const string &str) string() string(const char *s,size_type n) template<class Iter> string(Iter begin, Iter end) string(const string &s

GCC 4.9.0 发布,提升 C++11 和 C++14 特性

from :http://www.oschina.net/news/51084/gcc-4-9-0 GCC 4.9.0 发布,此版本是个主要版本更新,包括了 GCC 4.8.x 系列和之前的 GCC 版本都没有的新特性,新特性非常之多.下载地址:http://gcc.gnu.org/mirrors.html 警告 移除 mudflap 运行时检查器,mudflap 选项保留,但没有任何效果. 对一些很多老的系统和一些不维护的平台的支持在 4.9 版本中声明为过世的,下一个版本将永久删除,例如 S

GCC 4.9.0 公布,提升 C++11 和 C++14 特性

from :http://www.oschina.net/news/51084/gcc-4-9-0 GCC 4.9.0 公布,此版本号是个主要版本号更新,包含了 GCC 4.8.x 系列和之前的 GCC 版本号都没有的新特性,新特性很之多.下载地址:http://gcc.gnu.org/mirrors.html 警告 移除 mudflap 执行时检查器,mudflap 选项保留,但没有不论什么效果. 对一些非常多老的系统和一些不维护的平台的支持在 4.9 版本号中声明为过世的,下一个版本号将永久

Boost 1.61.0 Library Documentation

http://www.boost.org/doc/libs/1_61_0/ Boost 1.61.0 Library Documentation Accumulators Framework for incremental calculation, and collection of statistical accumulators. Author(s): Eric Niebler First Release: 1.36.0 Standard: Categories: Math and nume

c++的关联容器入门(map and set)

C++的关联容器主要是两大类map和set 我们知道谈到C++容器时,我们会说到 顺序容器(Sequence containers),关联容器(Associative containers),无序关联容器(Unordered associative containers)以及容器适配器(Container adaptors), 另外,我相信,这些抽象的容器概念,应该是所有高级语言都有的.本文重点阐述关联容器. Associative containers implement sorted dat

Understand the Qt containers(有对应表)

Container classes are one of the cornerstones of object-oriented programming, invaluable tools that free us from having to permanently think about memory management. Qt comes with its own set of container classes, closely modeled after those in the S

11.STL简单set和multiset的实现

set的特性是所有元素都会根据键值自动排序,set的元素不像map那样同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值.Set不允许两个元素拥有相同的键值.不能通过迭代器修改set元素的值. multiset和set的唯一区别在于multiset允许键值重复. 我们采用红黑树作为set和multiset的底层数据结构,set和multiset的实现完完全全是在红黑树的基础上封装的一层接口,所有的set和multiset操作都转而调用红黑树的API.有关STL红黑