STL之set

5 篇文章 0 订阅

续篇~~上一篇简要的列了一下红黑树的底层设计


关联式容器分为set(集合)、map(映射表),以及两个衍生体multiset(多键集合)、multimap(多键映射表),它们的底层机制都是RB_tree(红黑树),RB_tree也是一个独立容器,只不过不对外界开放。

1、set
set的特性,所有元素会根据键值(key)自动被排序,set和map不一样,set的键值(key)就是实值(value),实值(value)就是键值(key),而且set中的键值不允许重复
所以想通过迭代器去改变set的value值也是不被允许的,因为它的实值就是键值,关系到整个集合的排序,所以它也将迭代器设计成constant iterator.
另一个比较重要的特性就是set与list有某些相同的性质,它的迭代器在插入或者删除之后也不会失效,已经被删除的那个迭代器例外。

// 比较器默认采用less,内部按照升序排列
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set
{
public:
  //  在set中key就是value, value同时也是key
  typedef Key key_type;
  typedef Key value_type;

  // 使用的同一个比较函数
  typedef Compare key_compare;
  typedef Compare value_compare;

private:
  // 内部采用RBTree作为底层容器
  typedef rb_tree<key_type, value_type,
                  identity<value_type>, key_compare, Alloc> rep_type;
  rep_type t;   // 定义了一个RB_tree
public:
//typedef typename是用在模板里,告诉编译器,这是一个合法类型
  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::difference_type difference_type; 
  // 设置成const迭代器,set的键值不允许修改
  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;
 // 返回用于key比较的函数
  key_compare key_comp() const { return t.key_comp(); }
  // 由于set的性质, value比较和key使用同一个比较函数
  value_compare value_comp() const { return t.key_comp(); }

  // 声明了两个友元函数,重载了==和<操作符
  friend bool operator== __STL_NULL_TMPL_ARGS (const set&, const set&);
  friend bool operator< __STL_NULL_TMPL_ARGS (const set&, const set&);
}

set的插入一定要用RB_tree的insert_unique()而非insert_equal(),因为不允许相同的键值存在。multiset才用insert_equal( )

构造函数其一:
set(InputIterator first, InputIterator last)
: t(Compare()) { t.insert_unique(first, last); 

set的操作

  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(set<key,compare,Alloc>& x){t.swap(x.t)}

值得注意的就是删除和插入函数
注意不同版本之间的返回值和形参的不同

版本一:返回值为为一个pair对象
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.second);
}
版本二:返回一个迭代器
iterator insert(iterator position,const value_type& x);
版本三:
void inset(inputIterator first,inputIterator last);
//返回小于当前元素可插入的第一个位置
iterator lower_bound(const key_type& x)const
//返回大于当前元素可插的第一个位置
iterator upper_bound(const key_type& x)const
//返回与指定键值相等的元素区间
pair<iterator,iterator> equal_range(const key_type& x)const

2、set相关算法
set有四个强大的算法,set_union(并集)、set_intersection(交集)、set_different(差集)、set_symmetric_different(对称差集)
首先看看如何应用的:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
总之,在日常的使用中,set功能强大,遇到需要去重和排序的话,相当好用~~至于这四个set特有的函数,感兴趣的可以参考侯捷先生的《STL源码剖析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值