关联容器 — hash_map

hash_map和map的用法很相似,只是底层机制有所不同。

hash_map容器采用的底层机制是hash table代码:

template <class Key, class T, class HashFcn = hash<Key>,
          class EqualKey = equal_to<Key>,
          class Alloc = alloc>
class hash_map
{
private:
  typedef hashtable<pair<const Key, T>, Key, HashFcn,
                    select1st<pair<const Key, T> >, EqualKey, Alloc> ht;
  ht rep;     // 底层机制——hash table
  ....
}

注意,hashtable类型的第一个类型参数是pair,继续跟踪hashtable代码:

template <class Value, class Key, class HashFcn,
          class ExtractKey, class EqualKey,
          class Alloc>
class hashtable {   // hash table数据结构
public:
  typedef Key key_type;
  typedef Value value_type;

  ....
  typedef __hashtable_node<Value> node;
  typedef simple_alloc<node, Alloc> node_allocator; // 空间配置器

  vector<node*,Alloc> buckets;  // 桶的集合
  ....
}

可以看出,Value或value_type的实际类型是一个pair,那么一个node中也存储了一个pair,而vector中的bucket还是指针不变。即每个bucket指向一串nodes,每个node中存放一个pair<key, value>。这和map容器是类似的,map容器底层的红黑树中,每个节点也是存储了一个pair。

下面是测试代码:

#include <iostream>
#include <hash_map>
#include <cstring>

using namespace std;
using namespace __gnu_cxx;

struct eqstr {
    bool operator() (const char *s1, const char *s2) const
    { return strcmp(s1, s2) == 0; }
};

int main()
{
    hash_map<const char*, int, hash<const char *>, eqstr> m;

    // 两种插入方法
    m["hello"] = 123;
    m["byebye"] = 234;
    m["test"] = 345;
    m.insert(pair<const char *, int>("a", 222));

    hash_map<const char*, int, hash<const char *>, eqstr>::iterator iter = m.begin();

    for ( ; iter != m.end(); ++iter)
        cout << iter->first << ‘ ‘ << iter->second << endl;

    return 0;
}

运行结果:

由于hash_map提供的默认键值比较标准为equal_to:

template <class T>
struct equal_to : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const { return x == y; }
};

这个仿函数只是简单的拿两个值进行比较,如果传入的key为const char *,那么比较的将会是两个地址,这不是我们想要的。正确的字符串比较应该是逐个字符进行比较,这就是为什么要定义eqstr的原因。

从运行结果也能够看出,和hash_set一样,hash_map内的元素无特定排序。

参考:

《STL源码剖析》 P275.

关联容器 — hash_map,布布扣,bubuko.com

时间: 2024-10-13 09:52:49

关联容器 — hash_map的相关文章

STL源码剖析---关联容器

标准关联容器分为set和map两大类,包括multiset和multimap,这些容器的底层机制都是RB-tree.标准之外的关联容器有hashtable 以及以此hash table为底层机制而完成的hash_set(散列集合) hash_map(散列映射表) hash_multiset  hash_multimap. 序列和关联容器各自的内部关系是内含的,例如heap内含一个vector,priority_quehe内含一个heap,stack和queue都内含一个deque,set/map

关联容器(底层机制) — hashtable

C++ 11已将哈希表纳入了标准之列.hashtable是hash_set.hash_map.hash_multiset.hash_multimap的底层机制,即这四种容器中都包含一个hashtable. 解决碰撞问题的办法有许多,线性探测.二次探测.开链等等.SGI STL的hashtable采用的开链方法,每个hash table中的元素用vector承载,每个元素称为桶(bucket),一个桶指向一个存储了实际元素的链表(list),链表节点(node)结构如下: template <cl

《STL源码剖析》——第五、六:关联容器与算法

第五章.关联容器  5.0.关联容器 标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表).这些容器的底层机制均以RB-tree(红黑树)完成.RB-tree也是一个独立容器,但并不开放给外界使用. SGISTL还提供了一个不在标准规格之列的关联式容器:hash_table (散列表),以及以此hash_table为底层机制而完成的hash_set(散列集合).hash_map(散列映射表).hash_

STL 笔记(二) 关联容器 map、set、multimap 和 multimap

STL 关联容器简单介绍 关联容器即 key-value 键值对容器,依靠 key 来存储和读取元素. 在 STL 中,有四种关联容器,各自是: map 键值对 key-value 存储,key 不可反复,即一个 key 仅仅能相应一个 value, 相应头文件<map> multimap 键值对 key-value 存储,key 能够反复,即一个 key 能够相应多个 value, 相应头文件<map> set 仅仅有 key, key 不可反复,相应头文件<set>

实例讲解,set,multiset,map,multimap关联容器

测试环境:windows 7 vs2010 内部元素有序排列,新元素插入的位置取决于它的值,查找速度快. 除了各容器都有的函数外,还支持以下成员函数: find: 查找等于某个值的元素(x小于y和y小于x同时不成立即为相等) lower_bound: 查找某个下界 upper_bound: 查找某个上界 equal_range: 同时查找上界和下界 count:计算等于某个值的元素个数(x小于y和y小于x同时不成立即为相等) insert: 用以插入一个元素或一个区间 在学习关联容器之前,我们先

【足迹C++primer】38、关联容器操作(2)

关联容器操作(2) map的下标操作 map的下标操作 map和unordered_map容器提供了下标运算符合一个对应的at函数 对于一个map使用下标操作,其行为与数组或vector上的下标操作很不相同: 使用一个不再容器中的关键字作为下标,会添加一个此关键字的元素到map中 map和unordered_map的下标操作 c[k] 返回关键字为k的元素,如果关键字k不再c中,添加一个关键字为k的元素,对其进行值初始化 c.at(k) 访问关键字为k的元素,带参数检测,如果k不再c重那么返回一

STL_关联容器 VS C++ hashmap

红黑树和哈希表区别: http://m.blog.csdn.net/article/details?id=52133283 关于STL中关联容器的几个问题: (1)为何map和set的插入删除效率比用其他序列容器高? 大部分人说,很简单,因为对于关联容器来说,不需要做内存拷贝和内存移动.说对了,确实如此.set容器内所有元素都是以节点的方式来存储,其节点结构和链表差不多,指向父节点和子节点.结构图可能如下: A   / \ B C / \ / \  D E F G 因此插入的时候只需要稍做变换,

[C++]高效使用关联容器的一些建议

关联容器 本文介绍在关联容器中常见的一些的问题以及提升使用关联容器的建议. 1. 理解相等(equality)和等价(equivalence)的区别. 相等是以operator==为基础的.等价是以operator<为基础的. 例如find的定义是相等,他用operator==来判断,这是比较容易理解的. 而等价关系是以"在已排序的区间中对象值的相对顺序"为基础的.也就是说,如果两个值中任何一个(按照既定的排列顺序)都在另一个的前面,那么他们就是等价的. !(w1 < w2

C++之容器(关联容器)

C++之容器(关联容器) 关联容器和顺序容器的本质区别:关联容器是通过键存取和读取元素.顺序容器通过元素在容器中的位置顺序存储和访问元素.因此,关联容器不提供front.push_front.pop_front.back.push_back以及pop_back,此外对于关联容器不能通过容器大小来定义,因为这样的话将无法知道键所对应的值什么. 两个基本的关联容器类型是map和set.map的元素以键-值对的形式组织:键用作元素在map的索引,而值则表示所存储和读取的数据.set仅包含一个键,并有效