SGISTL源码探究-关联式容器:multiset

来源:互联网 发布:淘宝想开情趣用品店 编辑:程序博客网 时间:2024/06/06 08:23

前言

multisetset的实现十分相似,除了允许键值重复之外,几乎一样。而实现允许键值重复这一功能的是红黑树中提供的操作insert_equal,接下来我们就进入到它的源码,顺便也复习一下set,看看到底和set有什么不同。

multiset的实现

#ifndef __STL_LIMITED_DEFAULT_TEMPLATEStemplate <class Key, class Compare = less<Key>, class Alloc = alloc>#elsetemplate <class Key, class Compare, class Alloc = alloc>#endif/* 模板参数这里是一样的 * key为键值的类型 * compare为大小比较的标准 * alloc为空间配置器 */class multiset {public:  // typedefs:  /* 类型的别名声明   * key_type和value_type都设置成key   * key_compare和value_compare都设置成compare   */  typedef Key key_type;  typedef Key value_type;  typedef Compare key_compare;  typedef Compare value_compare;private:  //红黑树成员的定义  typedef rb_tree<key_type, value_type,                  identity<value_type>, key_compare, Alloc> rep_type;  rep_type t;  // red-black tree representing multisetpublic:  /* 一些指针、引用、迭代器的类型别名 */  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;  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;  // allocation/deallocation  //构造函数  multiset() : t(Compare()) {}  explicit multiset(const Compare& comp) : t(comp) {}  /* 以下是范围构造   * 里面调用的是insert_equal   * 而不是像set那样调用的是insert_unique   */#ifdef __STL_MEMBER_TEMPLATES  template <class InputIterator>  multiset(InputIterator first, InputIterator last)    : t(Compare()) { t.insert_equal(first, last); }  template <class InputIterator>  multiset(InputIterator first, InputIterator last, const Compare& comp)    : t(comp) { t.insert_equal(first, last); }#else  multiset(const value_type* first, const value_type* last)    : t(Compare()) { t.insert_equal(first, last); }  multiset(const value_type* first, const value_type* last,           const Compare& comp)    : t(comp) { t.insert_equal(first, last); }  multiset(const_iterator first, const_iterator last)    : t(Compare()) { t.insert_equal(first, last); }  multiset(const_iterator first, const_iterator last, const Compare& comp)    : t(comp) { t.insert_equal(first, last); }#endif /* __STL_MEMBER_TEMPLATES */  //拷贝构造函数  multiset(const multiset<Key, Compare, Alloc>& x) : t(x.t) {}  multiset<Key, Compare, Alloc>&  operator=(const multiset<Key, Compare, Alloc>& x) {    t = x.t;    return *this;  }  // accessors:  //常用函数,和set一样  key_compare key_comp() const { return t.key_comp(); }  value_compare value_comp() const { return t.key_comp(); }  iterator begin() const { return t.begin(); }  iterator end() const { return t.end(); }  reverse_iterator rbegin() const { return t.rbegin(); }  reverse_iterator rend() const { return t.rend(); }  bool empty() const { return t.empty(); }  size_type size() const { return t.size(); }  size_type max_size() const { return t.max_size(); }  void swap(multiset<Key, Compare, Alloc>& x) { t.swap(x.t); }  // insert/erase  /* 插入操作,可见调用的是insert_equal   * 而不是像set里面调用的是insert_unique   */  iterator insert(const value_type& x) {    return t.insert_equal(x);  }  iterator insert(iterator position, const value_type& x) {    typedef typename rep_type::iterator rep_iterator;    return t.insert_equal((rep_iterator&)position, x);  }#ifdef __STL_MEMBER_TEMPLATES    template <class InputIterator>  void insert(InputIterator first, InputIterator last) {    t.insert_equal(first, last);  }#else  void insert(const value_type* first, const value_type* last) {    t.insert_equal(first, last);  }  void insert(const_iterator first, const_iterator last) {    t.insert_equal(first, last);  }#endif /* __STL_MEMBER_TEMPLATES */  /* 删除操作,这些和set一样 */  void erase(iterator position) {    typedef typename rep_type::iterator rep_iterator;    t.erase((rep_iterator&)position);  }  size_type erase(const key_type& x) {    return t.erase(x);  }  void erase(iterator first, iterator last) {    typedef typename rep_type::iterator rep_iterator;    t.erase((rep_iterator&)first, (rep_iterator&)last);  }  /* 一些常用的操作,和set一样 */  void clear() { t.clear(); }  // multiset operations:  iterator find(const key_type& x) const { return t.find(x); }  size_type count(const key_type& x) const { return t.count(x); }  /* 返回指向第一个比x大的元素的迭代器 */  iterator lower_bound(const key_type& x) const {    return t.lower_bound(x);  }  /* 返回指向第一个比x小的元素的迭代器 */  iterator upper_bound(const key_type& x) const {    return t.upper_bound(x);  }  pair<iterator,iterator> equal_range(const key_type& x) const {    return t.equal_range(x);  }  //重载==操作符和<操作符  friend bool operator== __STL_NULL_TMPL_ARGS (const multiset&,                                               const multiset&);  friend bool operator< __STL_NULL_TMPL_ARGS (const multiset&,                                              const multiset&);};template <class Key, class Compare, class Alloc>inline bool operator==(const multiset<Key, Compare, Alloc>& x,                       const multiset<Key, Compare, Alloc>& y) {  return x.t == y.t;}template <class Key, class Compare, class Alloc>inline bool operator<(const multiset<Key, Compare, Alloc>& x,                      const multiset<Key, Compare, Alloc>& y) {  return x.t < y.t;}#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDERtemplate <class Key, class Compare, class Alloc>inline void swap(multiset<Key, Compare, Alloc>& x,                 multiset<Key, Compare, Alloc>& y) {  x.swap(y);}#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */

例子

#include <iostream>#include <set>using namespace std;int main(){    multiset<int> multis;    //允许插入相同的键值元素    //如果是在set中,插入重复的元素是不会成功的    multis.insert(1);    multis.insert(1);    multis.insert(1);    multis.insert(3);    multis.insert(3);    multiset<int>::iterator ite = multis.lower_bound(2);    cout << *ite << endl;    multiset<int>::iterator ite1 = multis.begin();    multiset<int>::iterator ite2 = multis.end();    while(ite1 != ite2)    {        cout << *ite1 << endl;        ite1++;    }    return 0;}

小结

本小节介绍了和set类似的multiset,它们两者唯一的不同就是set不允许重复的元素,而multiset允许重复的元素存在。并且底层就是因为调用红黑树的插入操作函数不同造成的这种区别,set调用insert_unique进行插入操作,multiset调用insert_equal进行插入操作。
在下一节中,我们将介绍和map相近的multimap

原创粉丝点击