目录
T: set中存放元素的类型,实际在底层存储
Compare:set中元素默认按照小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理
| 函数声明 | 函数功能 |
|---|---|
set (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()); | 构造空的set |
set (InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()); | 用[first,last)区间中的元素构造set |
set (const set& x); | set的拷贝构造 |
| 函数声明 | 函数功能 |
| iterator begin(); | 返回set中起始位置元素的迭代器 |
| iterator end(); | 返回set中最后一个元素后面的迭代器 |
| const_iterator cbegin() const; | 返回set中起始位置元素的const迭代器 |
| const_iterator end() const; | 返回set中最后一个元素后面的const迭代器 |
| reverse_iterator rbegin(); |
返回set第一个元素的反向迭代器,即end
|
| reverse_iterator rend(); |
返回set最后一个元素下一个位置的反向迭代器,即rbegin
|
| const_reverse_iterator crbegin() const; |
返回set第一个元素的反向const迭代器,即cend
|
| const_reverse_iterator crend() const; |
返回set最后一个元素下一个位置的反向const迭代器,即crbegin
|
| 函数声明 | 函数功能 |
|
bool empty ( ) const;
|
检测set是否为空,空返回true,否则返回false
|
|
size_type size() const;
|
返回set中有效元素的个数
|
| 函数声明 | 函数功能 |
|
pair |
在set中插入元素x,实际插入的是 |
|
void erase ( iterator position);
|
删除set中position位置上的元素
|
|
size_type erase (const key_type& x )
|
删除set中值为x的元素,返回删除的元素的个数
|
|
void erase ( iterator fifirst, iterator last )
|
删除set中[fifirst, last)区间中的元素
|
|
void swap ( set
st );
|
交换set中的元素
|
|
void clear ( )
|
将set中的元素清空
|
|
iterator find ( const key_type& x ) const
|
返回set中值为x的元素的位置
|
|
size_type count ( const key_type& x ) const
|
返回set中值为x的元素的个数
|

key: 键值对中key的类型
T: 键值对中value的类型
Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器
| 函数构造 | 函数功能 |
map (const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type()); | 构造空的set |
map (InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type()); | 用[first,last)区间中的元素构造map |
map (const map& x); | map的拷贝构造 |
| 函数声明 | 函数功能 |
| iterator begin(); | 返回map中起始位置元素的迭代器 |
| iterator end(); | 返回map中最后一个元素后面的迭代器 |
| const_iterator cbegin() const; | 返回map中起始位置元素的const迭代器 |
| const_iterator end() const; | 返回map中最后一个元素后面的const迭代器 |
| reverse_iterator rbegin(); |
返回map第一个元素的反向迭代器,即end
|
| reverse_iterator rend(); |
返回map最后一个元素下一个位置的反向迭代器,即rbegin
|
| const_reverse_iterator crbegin() const; |
返回map第一个元素的反向const迭代器,即cend
|
| const_reverse_iterator crend() const; |
返回map最后一个元素下一个位置的反向const迭代器,即crbegin
|
| 函数声明 | 函数功能 |
|
bool empty ( ) const;
|
检测set是否为空,空返回true,否则返回false
|
|
size_type size() const;
|
返回set中有效元素的个数
|
|
mapped_type& operator[] (const key_type& k)
|
返回去key对应的value
|
| 函数声明 | 函数功能 |
|
pair |
在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功
|
|
void erase ( iterator position);
|
删除position位置上的元素
|
|
size_type erase (const key_type& x )
|
删除值为x的元素
|
|
void erase ( iterator fifirst, iterator last )
|
删除[fifirst, last)区间中的元素
|
|
void swap ( map
mp );
|
交换map中的元素
|
|
void clear ( )
|
将map中的元素清空
|
|
iterator find ( const key_type& x ) const
| 返回map中值为x的元素的位置,找到返回该元素的位置的const迭代器,否则返回cend |
|
size_type count ( const key_type& x ) const
|
返回值为x的元素的个数
|
1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是
3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。
4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。
5. multiset底层结构为二叉搜索树(红黑树)。
- template<class T>
- struct AVLTreeNode
- {
- AVLTreeNode(const T& data = T())
- : _pLeft(nullptr)
- , _pRight(nullptr)
- , _pParent(nullptr)
- , _data(data)
- , _bf(0)
- {}
-
- AVLTreeNode
* _pLeft; - AVLTreeNode
* _pRight; - AVLTreeNode
* _pParent; - T _data;
- int _bf; // 节点的平衡因子
- };
- bool Insert(const T& data)
- {
- if (_pRoot == nullptr)
- {
- _pRoot = new Node(data);
- _pRoot->_bf = 0;
- return true;
- }
-
- Node* parent = nullptr;
- Node* cur = _pRoot;
- while (cur)
- {
- if (cur->_data < data)
- {
- parent = cur;
- cur = cur->_pRight;
- }
- else if (cur->_data > data)
- {
- parent = cur;
- cur = cur->_pLeft;
- }
- else
- {
- return false;
- }
- }
- cur = new Node(data);
- if (parent->_data > data)
- {
- parent->_pLeft = cur;
- }
- else
- {
- parent->_pRight = cur;
- }
- cur->_pParent = parent;
-
- while (parent)
- {
- if (cur == parent->_pRight)
- {
- parent->_bf++;
- }
- else
- {
- parent->_bf--;
- }
-
- if (parent->_bf == 0)
- {
- break;
- }
- else if (parent->_bf == 1 || parent->_bf == -1)
- {
- cur = cur->_pParent;
- parent = parent->_pParent;
- }
- else if (parent->_bf == 2 || parent->_bf == -2)
- {
- if (parent->_bf == 2 && cur->_bf == 1)
- {
- RotateL(parent);
- }
- else if (parent->_bf == -2 && cur->_bf == -1)
- {
- RotateR(parent);
- }
- else if (parent->_bf == -2 && cur->_bf == 1)
- {
- RotateLR(parent);
- }
- else if (parent->_bf == 2 && cur->_bf == -1)
- {
- RotateRL(parent);
- }
- break;
- }
- else
- {
- assert(false);
- }
- }
- return true;
- }
1. 新节点插入较高左子树的左侧---左左:右单旋 
- void RotateR(Node* pParent)
- {
- Node* subL = pParent->_pLeft;
- Node* subLR = subL->_pRight;
-
- pParent->_pLeft = subLR;
- if (subLR)
- {
- subLR->_pParent = pParent;
- }
-
- Node* ppNode = pParent->_pParent;
-
- subL->_pRight = pParent;
- pParent->_pParent = subL;
-
- if (pParent == _pRoot)
- {
- _pRoot = subL;
- _pRoot->_pParent = nullptr;
- }
- else
- {
- if (ppNode->_pLeft == pParent)
- {
- ppNode->_pLeft = subL;
- }
- else
- {
- ppNode->_pRight = subL;
- }
- subL->_pParent = ppNode;
- }
- subL->_bf = pParent->_bf = 0;
- }

- void RotateL(Node* pParent)
- {
- Node* subR = pParent->_pRight;//父节点的右孩子
- Node* subRL = subR->_pLeft;//subR的左孩子
-
- pParent->_pRight = subRL;
- if (subRL)//若subRL不为空,将subRL的父亲改成pParent
- {
- subRL->_pParent = pParent;
- }
-
- Node* ppNode = pParent->_pParent;//记录父节点的父节点
-
- subR->_pLeft = pParent;//将pParent设为subR的左孩子
- pParent->_pParent = subR;//将pParent的父节点设为subR
-
- if (pParent == _pRoot)//如果是根节点
- {
- _pRoot = subR;
- _pRoot->_pParent = nullptr;
- }
- else
- {
- if (pParent == ppNode->_pLeft)
- {
- ppNode->_pLeft = subR;
- }
- else
- {
- ppNode->_pRight = subR;
- }
- subR->_pParent = ppNode;
- }
- pParent->_bf = 0;
- subR->_bf = 0;
- }
3. 新节点插入较高左子树的右侧---左右:先左单旋再右单旋

- void RotateLR(Node* pParent)
- {
- Node* subL = pParent->_pLeft;
- Node* subLR = subL->_pRight;
- int bf = subLR->_bf;
-
- RotateL(pParent->_pLeft);
- RotateR(pParent);
-
- if (bf == 0)
- {
- pParent->_bf = 0;
- subL->_bf = 0;
- subLR->_bf = 0;
- }
- else if (bf == -1)
- {
- pParent->_bf = 1;
- subL->_bf = 0;
- subLR->_bf = 0;
- }
- else if (bf == 1)
- {
- pParent->_bf = 0;
- subL->_bf = -1;
- subLR->_bf = 0;
- }
- else
- {
- assert(false);
- }
- }
4. 新节点插入较高右子树的左侧---右左:先右单旋再左单旋

- void RotateRL(Node* pParent)
- {
- Node* subR = pParent->_pRight;
- Node* subRL = subR->_pLeft;
- int bf = subRL->_bf;
-
- RotateR(pParent->_pRight);
- RotateL(pParent);
-
- if (bf == 0)
- {
- subRL->_bf = 0;
- pParent->_bf = 0;
- subR->_bf = 0;
-
- }
- else if (bf == -1)
- { subRL->_bf = 0;
- pParent->_bf = 0;
- subR->_bf = 1;
-
- }
- else if (bf == 1)
- { subRL->_bf = 0;
- pParent->_bf = -1;
- subR->_bf = 0;
-
- }
- else
- {
- assert(false);
- }
- }
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

- // 节点的颜色
- enum Color
- {
- RED,
- BLACK
- };
- // 红黑树节点的定义
- template<class ValueType>
- struct RBTreeNode
- {
- RBTreeNode(const ValueType& data = ValueType(),Color color = RED)
- : _pLeft(nullptr)
- , _pRight(nullptr)
- , _pParent(nullptr)
- , _data(data)
- , _color(color)
- {}
- RBTreeNode
* _pLeft; // 节点的左孩子 - RBTreeNode
* _pRight; // 节点的右孩子 - RBTreeNode
* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给出该字段) - ValueType _data; // 节点的值域
- Color _color; // 节点的颜色
- };
2. 检测新节点插入后,红黑树的性质是否造到破坏
因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:
情况一: cur为红,p为红,g为黑,u存在且为红

情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑

情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转,则转换成了情况2
- pair
bool > Insert(const T& data) - {
- Node*& pRoot = GetRoot();
- if (pRoot == nullptr)
- {
- pRoot = new Node(data);
- pRoot->_parent = _pHead;
- pRoot->_color = BLACK;
- _size = 1;
- return make_pair((iterator)pRoot, true);
- }
- else
- {
- KeyOfValue Kof;
- Node* cur = pRoot;
- Node* parent = nullptr;
- while (cur)
- {
- if (Kof(cur->_data) > Kof(data))
- {
- parent = cur;
- cur = cur->_left;
- }
- else if (Kof(cur->_data) < Kof(data))
- {
- parent = cur;
- cur = cur->_right;
- }
- else
- {
- return make_pair((iterator)cur, false);
- }
- }
-
- cur = new Node(data);
- if (Kof(parent->_data) > Kof(data))
- {
- parent->_left = cur;
- }
- else
- {
- parent->_right = cur;
- }
- cur->_parent = parent;
-
- while (parent != _pHead && parent->_color == RED)
- {
- Node* grandfater = parent->_parent;
- assert(grandfater);
- if (grandfater->_left == parent)
- {
- Node* uncle = grandfater->_right;
- if (uncle && uncle->_color == RED)
- {
- parent->_color = uncle->_color = BLACK;
- grandfater->_color = RED;
-
- cur = grandfater;
- parent = cur->_parent;
- }
- else
- {
- if (cur == parent->_left)
- {
- // g
- // p
- // c
- RotateR(grandfater);
- parent->_color = BLACK;
- grandfater->_color = RED;
- }
- else
- {
- // g
- // p
- // c
- RotateL(parent);
- RotateR(grandfater);
-
- cur->_color = BLACK;
- grandfater->_color = RED;
- }
- break;
- }
- }
- else
- {
- Node* uncle = grandfater->_left;
- if (uncle && uncle->_color == RED)
- {
- parent->_color = uncle->_color = BLACK;
- grandfater->_color = RED;
-
- cur = grandfater;
- parent = cur->_parent;
- }
- else
- {
- if (cur == parent->_right)
- {
- // g
- // p
- // c
- RotateL(grandfater);
- parent->_color = BLACK;
- grandfater->_color = RED;
- }
- else
- {
- // g
- // p
- // c
- RotateR(parent);
- RotateL(grandfater);
-
- cur->_color = BLACK;
- grandfater->_color = RED;
- }
- break;
- }
- }
- }
- }
- _size++;
- pRoot->_color = BLACK;
- return true;
- }