【c++从菜鸡到王者】第二篇:STL关联容器-(multi)Set

本文详细介绍了C++ STL中的set和multiset容器,强调了它们基于红黑树的实现和自动排序特性。set不允许键值重复,而multiset则允许。此外,文章还探讨了插入、删除和查找操作,并提供了源代码概览,展示了两者如何在内部处理这些操作。同时,提及了set与multiset在插入策略上的差异,set使用insert_unique(),而multiset使用insert_equal()。
摘要由CSDN通过智能技术生成

set

  • set特性:所有元素会根据键值来自动排序;杜绝写入操作,通过下面迭代器的源代码可以看出,因为set要根据键值排序,如果插入会破坏set组织;客户端对元素进行插入或者是删除操作时,其他元素的迭代器都是有效的,除了被删除的元素的迭代器除外;标准set容器是以红黑树为底层机制的,也可以用hash_set为底层机制。
template<class T,class Compare=less<Key>,class Alloc =alloc>
class set{
    public:
       typedef Key Key_type;
       typedef Key value_type;
       typedef Compare Key_compare;
       typedef Compare key_compare;
    private:
       template <class T>
       struct identify:public unary_function<T,T>{
           const T& operator()(const T& x)const{return x;}
       };//仿函数章节中的配接器
       typedef rb_tree<key_type,value_type,identify<value_type>,key_compare,Alloc>rep_type
       //采用红黑树来做set的底层
       rep_type t;
     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;
       typedef typename rep_type::const_itereator 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使用的是rb_tree的insert_unique(),multiset使用的是insert_equal();
     //以下是构造函数
     set():t(Compare()){}
     explicit set(const Compare& comp):t(comp){}
     template<class InputIterator>
     set(InputIterator first,InputIterator last):t(Compare()){t.insert_unique(first,last);}
     template<class InputIterator>
     set(InputIterator first,InputIterator last,const Compare&comp):t(comp)                                                                                          {t.insert_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行为,Rb_tree都已提供,set只需要调用即可
     key_compare key_comp()const{return t.key_comp();}
     value_compare value_comp()const{return t.value_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.end();}
     bool empty()const{return t.empty();}
     size_type size()const{return t.size();}
     size_type max_size()const{return t.max_size();}
     void swap(set<Key,Compare,Alloc>&x){t.swap(x.t);}
     // insert/erase3种不同类型的inset与erase
     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);
         return pair<iterator,bool>(p.first,p.secend);
     }
     iterator insert(iterator position,const value_type&x){
         typedef typename rep_tree::iterator rep_iterator;
         return t.insert_unique((rep_iterator&)position,x);
     }
     template<class InputIterator>
     void insert(InputIterator first,InputIterator last){
         t.insert_unique(first,last);
     }
     void erase(iterator pozition){
          typedef typename rep_tree::iterator rep_iterator;
          t.erase((rep_iterator)&pozition);
    }
     size_type erase(const key_value&x){
         return t.erase(x);
     }
     void erase(iteratro first,iterator last){
         typedef typename rep_tree::iterator rep_iterator;
         t.erase((rep_iterator)&first,(rep_iterator)&last);
     }
     void clear(){t.clear();}
     //set operations
     iteratro find(const value_type&x)const{return t.find(x);}
     size_type count(const key_type&x)const{return t.count(x);}
     iterator lower_bound(const key_type&x)const{return t.lower_bound(x);}
     iteratoe_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);
     }
    //_STL_NULL_TMPL_ARGS展开为<>
     friend bool operator==_STL_NULL_TMPL_ARGS(const set&,const set&);
     friend bool operator<_STL_NULL_TMPL_ARGS(const set&,const set&);
};
template<class key,class Compare ,class Alloc>
    inline bool operator==(const set<Key,Compare,Alloc>&x,const set<Key,Compare,Alloc>&y){
     return x.t==y.t;
}
template<class key,class Compare ,class Alloc>
    inline bool operator<(const set<Key,Compare,Alloc>&x,const set<Key,Compare,Alloc>&y){
     return x.t<y.t;
}

multiset/multimap

  • multiset和multimap的特性以及用法都跟set与map相同,唯一区别是前者允许键值重复,因此它采用的是红黑树的insert_equal()。下面分别列出这两个容器源代码的概要,只列出他们与set/map不同之处
template<class T,class Compare=less<Key>,class Alloc>
class multiset{
    template<class InputInterator>
    multiset(InputInterator first,InputInterator last):t(Compare){t.insert_equal(first,last);}
    //下面这个适用于自己写比较函数
    multiset(InputInterator first,InputInterator last):t(comp){t.insert_equal(first,last);}
    iterator insert(const value_type& x){return t.insert_equal(x);}
    iterator insert(iterator position,const value_type&x){
        typedef typename rep_tree::iterator rep_iterator;
        return t.insert_equal((rep_iterator&)position,x);
    }
    template<class InputInterator>
    void insert(InputInterator first,InputInterator last){
        t.insert_equal(first,last);
    }
    //其余的都与set相同
};
//multimap的源代码的不同之处与set和multiset的不同之处一样
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值