看了前面的底层封装后,其实封装的过程及方法都大差不差,unordered_map && unordered_set 也是如此,所以本篇就简单提及一些细节,具体最详细的一些部分可以去看前面的文章

传送门:C++效率掌握之STL库:list底层剖析及迭代器万字详解

传送门:C++效率掌握之STL库:map && set底层剖析及迭代器万字详解

unordered_map、unordered_set的基本结构

🚩unordered_set:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
template<class K, class V>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename hash_bucket::HashTable<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename hash_bucket::HashTable<K, K, SetKeyOfT>::const_iterator const_iterator;


const_iterator begin() const
{
return _ht.begin();
}

const_iterator end() const
{
return _ht.end();
}

pair<const_iterator, bool> insert(const K& key)
{
pair<typename hash_bucket::HashTable<K, K, SetKeyOfT>::iterator, bool> ret = _ht.Insert(key);
return pair<const_iterator, bool>(ret.first, ret.second);
}
private:
hash_bucket::HashTable<K, K, SetKeyOfT> _ht;
};

🚩unordered_map:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
template<class K, class V>
class unordered_map
{
struct MapKeyOfT
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

iterator begin()
{
return _ht.begin();
}

iterator end()
{
return _ht.end();
}

const_iterator begin() const
{
return _ht.begin();
}

const_iterator end() const
{
return _ht.end();
}

pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _ht.Insert(kv);
}

V& operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
return ret.first->second;
}
private:
hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT> _ht;
};

unordered_set 虽然事 k-k 类型,unordered_mapk-v 类型,但是实际上这两个类共用一个哈希表,准确来说是共用同一个模板类型,unordered_set<K,K>unordered_map<K,pair<K,V>>

普通迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
template<class K, class T, class Ptr, class Ref, class KeyOfT, class HashFunc>
struct HTIterator
{
typedef HashNode<T> Node;
typedef HTIterator<K, T, Ptr, Ref, KeyOfT, HashFunc> Self;
typedef HTIterator<K, T, T*, T&, KeyOfT, HashFunc> Iterator;

Node* _node;
const HashTable<K, T, KeyOfT, HashFunc>* _pht;

/*HTIterator(Node* node, HashTable<K, T, KeyOfT, HashFunc>* pht)
:_node(node)
,_pht(pht)
{}*/

HTIterator(Node* node, const HashTable<K, T, KeyOfT, HashFunc>* pht)
:_node(node)
, _pht(pht)
{
}

// 普通迭代器时,他是拷贝构造
// const迭代器时,他是构造
HTIterator(const Iterator& it)
:_node(it._node)
, _pht(it._pht)
{
}

Ref operator*()
{
return _node->_data;
}

Ptr operator->()
{
return &_node->_data;
}

Self& operator++()
{
if (_node->_next)
{
// 当前桶还没完
_node = _node->_next;
}
else
{
KeyOfT kot;
HashFunc hf;
size_t hashi = hf(kot(_node->_data)) % _pht->_table.size();
// 从下一个位置查找查找下一个不为空的桶
++hashi;
while (hashi < _pht->_table.size())
{
if (_pht->_table[hashi])
{
_node = _pht->_table[hashi];
return *this;
}
else
{
++hashi;
}
}

_node = nullptr;
}

return *this;
}

bool operator!=(const Self& s)
{
return _node != s._node;
}

bool operator==(const Self& s)
{
return _node == s._node;
}
};

typedef HTIterator<K, T, T*, T&, KeyOfT, HashFunc> Iterator 和构造函数是为 Insert 操作准备的,因为涉及到普通迭代器创建 const 迭代器

🔥值得注意的是: 有人说不是可以通过权限转化吗?但是权限转化是只有涉及引用和指针的类型时才会生效,而这里是模板参数之间的转化

const迭代器

unordered_set 本身无论是 const 迭代器还是普通迭代器都会被 typedefconst_iterator

对于 unordered_map 来说,key 是不允许改变的,value 是可以改变的,但是如果像 set 那样写的话 keyvalue 都不能修改了,所以直接在 pairkeyconst ,控制 value 即可

insert返回值 operator[]

🚩unordered_set:

1
2
3
4
5
6
pair<const_iterator, bool> insert(const K& key)
{
//return _ht.Insert(key);
pair<typename hash_bucket::HashTable<K, K, SetKeyOfT>::iterator, bool> ret = _ht.Insert(key);
return pair<const_iterator, bool>(ret.first, ret.second);
}

🚩unordered_map:

1
2
3
4
5
6
7
8
9
10
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _ht.Insert(kv);
}

V& operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
return ret.first->second;
}

这里的转化尤为复杂,一定要看之前文章的详细解析

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述