关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高

set

排序+去重

find找不到会返回end

lower_bound(val) 返回大于或者等于val的位置
upper_bound(val) 返回大于val的位置

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
int a[] = { 3,1, 2, 1, 6, 3, 8,3, 5,3};
multiset<int> s(a, a + sizeof(a) / sizeof(int));

// 排序
for (auto e : s)
{
cout << e << " ";
}
cout << endl;

cout << s.count(1) << endl;

// find时,如果有多个值,返回中序的第一个
auto pos = s.find(3);
while (pos != s.end())
{
cout << *pos << " ";
++pos;
}
cout << endl;

// 删除所有的3
s.erase(3);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;

pos = s.find(1);
if (pos != s.end())
{
s.erase(pos);
}
for (auto e : s)
{
cout << e << " ";
}
cout << endl;

map

重载的方括号

  • map中有这个key,返回value的引用。(查找、修改value)
  • map中没有这个key,会插入一个pair(key,V()),返回value的引用。(插入+修改)

具体点:

  • key在map中,返回pair(key_iterator, false) 这个pair是insert返回的
  • key不在map中,返回pair(new_key_iterator, true)

实现

1
2
3
4
5
V& operator[](const K& key)
{
pair<iterator,bool>ret=insert(make_pair(key, V()));
return (ret.first)->second;
}

map和set封装

迭代器(红黑树)

迭代器的begin是中序的第一个节点,也就是最左节点,这里将end设置为空,封装重点是++和–的逻辑

重载++

  • 右子树不为空,++就是找右子树中序第一个(最左节点)
  • 右子树为空,++找孩子不是父亲右的那个祖先

重载–

  • 左子树不为空,–就是找左子树的最右节点
  • 左子树为空,–找孩子不是父亲左的那个祖先

代码

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
83
84
85
template <class T, class Ref, class Ptr>
struct __RBTreeIterator
{
typedef RBTreeNode<T> Node;
Node *_node;
typedef __RBTreeIterator<T, Ref, Ptr> self;

__RBTreeIterator(Node *node) : _node(node)
{
}

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

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

self &operator++()
{
if (_node->_right) // 右子树不为空,右子树的最左就是下一个节点
{
Node *left = _node->_right;
while (left->_left) // 有个问题,当前节点如果是25,下个节点是27,left指向27,这样写,left变成空
{
left = left->_left;
}
_node = left;
}
else // 右子树为空,找孩子不是父亲右的那个祖先
{
Node *parent = _node->_parent;
Node *cur = _node;
while (parent && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}

_node = parent;
}

return *this;
}

self &operator--()
{
if (_node->_left) // 左子树不为空,左子树的最右就是下一个节点
{
Node *right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
else // 左子树为空,找孩子不是父亲左的那个祖先
{
Node *parent = _node->_parent;
Node *cur = _node;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}

_node = parent;
}

return *this;
}

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

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

map封装

map的红黑树 RBTree<K, pair<K, V>, MapKeyOfT>,第一个模板参数是key,第二个模板参数是pair

代码

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
template <class K, class V>
class map
{
struct MapKeyOfT
{
const K &operator()(const pair<K, V> &kv)
{
return kv.first;
}
};

public:
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;

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

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

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

V &operator[](const K &key)
{
return _t.insert(make_pair(key, V())).first->second;
}

private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};

set封装

set的红黑树 RBTree<K, K, SetKeyOfT>,第一个模板参数是key,第二个模板参数是pair

代码

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 set
{
struct SetKeyOfT
{
const K &operator()(const K &key)
{
return key;
}
};

public:
typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;

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

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

pair<iterator, bool> insert(const K &k)
{
return _t.insert(k);
}

private:
RBTree<K, K, SetKeyOfT> _t;
};