- set
set的特性是,所有的元素都会根据元素的键值自动排序。set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素拥有相同的键值。
不能通过set的迭代器改变set的元素值,因为set元素的值就是其键值,关系到set元素的排列规则。如果任意改变set元素值,会严重破坏set组织。
set拥有list相同的某些性质:当客户端对她进行元素新增操作或删除操作的时候,操作之前的所有迭代器,在操作完成之后都依然有效。当然,被删除的那个元素的迭代器必然是个例外。
标准的STL set 以红黑树作为底层的实现机制。
set的部分源码如下:
template <typename Key, typename Compare = less<Key>, typename Alloc = alloc>
//Compare缺省的情况使用递增排序
class set{
public:
//typedefs:
typedef Key key_type;
typedef Key value_type;
//注意,以下key_compare和value_compare使用同一个比较函数
typedef Compare key_compare;
typedef Compare key_compare;
private:
typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc> rep_type;
rep_type t;//采用红黑树来实现set
public:
typedef typename rep_type::const_pointer pointer;
typedef typename rep_type::const_pointer const_pointer;
typedef typename rep_type::const_reference reference;
typedef typename rep_type::const_reference const_reference;
typedef typename rep_type::const_iterator iterator;
//注意上一行Iterator是红黑树的const_iterator
typedef typename rep_type::const_iterator const_iterator;
typedef typename rep_type::const_reverse_iterator reverse_iterator;
typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
typedef typename rep_type::size_type size_type;
typedef typename rep_type::difference_type difference_type;
//下面几个是set的构造函数,注意,set一定使用RB-tree的insert_unique()而非insert_equal()
//multiset才使用红黑树的insert_equal(),因为set不允许相同键值存在,而multiset允许
set():t(Compare()){}
template<class InputIterator>
set(InputIterator first, InputIterator last):t(Compare()){t.inser_unique(first, last);}
template<class InputIterator>
set(InputIterator first, InputIterator last, const Compare& comp):t(comp){t.inser_unique(first, last);}
set(const set<Key, Compare, Alloc>& x):t(x.t){}
//赋值运算符
set<Key, Compare, Alloc>& operator=(const set<Key, Compare, Alloc>& x){
t = x.t;
return *this;
}
//下面的操作,红黑树已经提供,set只要调用即可
iterator begin() const {return t.begin();}//升序排序时指向最xiao节点
iterator end() const {return end();}//注意这个指向的是树的header,头结点的父节点(小技巧)
reverse_iterator rbegin() const {return t.rbegin();}//升序排序时指向最da节点
reverse_iterator rend() const {return t.rend();}
bool empty() const {return t.empty();}
size_type size() const {return t.size();}
typedef pair<iterator, bool> pair_iterator_bool;
pair<iterator, bool> insert(const value_type& x){
pair<typename rep_type::iterator, bool> p = t.insert_unique(x);//红黑树中insert_unique返回pair
return pair<iterator, bool>(p.first, p.second);
}
template <typename InputIterator>
void insert(InputIterator first, InputIterator last){
t.insert_unique(first, last);
}
void erase(iterator position){
typedef typename rep_type::iterator rep_iterator;
t.erase((rep_iterator&)position);
}
void erase(iterator first, iterator last){
typedef typename rep_type::iterator rep_iterator;
t.erase((rep_iterator&)first, (rep_iterator&)last);
size_type erase(const key_type& x){
return t.erase(x);
}
}
}
set所提供的函数简介:
- pair<iterator, bool> insert(const value_type& x)
这个函数底部调用的是insert_unique,返回的是一个pair,pair的第一个元素是插入的节点的迭代器,第二个元素是是否插入成功。
- begin(),rbegin(), end(),rend()
begin和end是正向迭代器,其他的两个是反向迭代器。假设红黑树是递增的(左子树的节点key < 根节点key < 右子树的节点key),这是begin()返回最小元素的迭代器而rbegin()返回最大元素的迭代器。end()和rend()都是header节点的迭代器。(header是STL实现红黑树时的小技巧,header的父亲指针指向root,header的左指针指向以root为根节点的最小元素,header的右指针指向以root为根节点的最大元素,root的父节点指向header)
- void insert(InputIterator first, InputIterator last)
这个函数的参数盛放是插入元素的容器的迭代器的开始位置和结束位置,注意返回值是void
- void erase(iterator position)
函数参数是要删除的元素的迭代器
- void erase(iterator first, iterator last)
函数第一个参数是要删除的元素段的最小元素的迭代器,第二个参数是要删除元素段的最大元素的迭代器
- size_type erase(const key_type& x)
函数参数是删除元素的值
- iterator find(const key_type& x)
返回x的迭代器
- size_type count(const key_type& x)
返回节点key值为x的节点个数
- multiset
multiset的特性及用法和set完全相同,唯一的差别在于multiset允许键值重复,因此它的插入操作采用的红黑树的insert_equal()而不是insert_unique()。注意insert_unique的返回值是pair前面已经介绍了,insert_equal的返回值是插入节点的Iterator,注意使用下面函数和set返回值的区别:
//返回值和set不一样
iterator insert(const value_type& x){
return t.insert_equal(x);
}