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

前言

在本小节中,我们将分析set容器,它的特性是,所有的元素会根据键值自动在set内部排序,set的键值就是实值,并且不允许两个相同值的元素在set中存在。并且set的元素值不能通过迭代器进行改变,因为一旦改变,就意味着set内部有序就被打破了。
set实现的机制和map一样,同样以红黑树作为底部实现,而关于set的操作,也只用调用红黑树提供的接口就行了。

set的实现

定义部分
#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Key, class Compare = less<Key>, class Alloc = alloc>
#else
template <class Key, class Compare, class Alloc = alloc>
#endif
class set {
public:
  // typedefs:
  //一些定义
  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 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;
  typedef typename rep_type::const_iterator const_iterator;
  typedef typename rep_type::size_type size_type;
  typedef typename rep_type::difference_type difference_type;
构造函数
  // allocation/deallocation
  //设置默认的大小比较标准
  set() : t(Compare()) {}
  //设置大小比较标准
  explicit set(const Compare& comp) : t(comp) {}

#ifdef __STL_MEMBER_TEMPLATES
  //调用红黑树的insert_unique进行范围构造
  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;
  }
常用操作
  // accessors:
  //返回键值的比较标准
  key_compare key_comp() const { return t.key_comp(); }
  //由于set中key和value是同一个,所以这里也调用key_comp
  value_compare value_comp() const { return t.key_comp(); }
  //返回起始迭代器(STL中红黑树中返回的是最左节点)
  iterator begin() const { return t.begin(); }
  //返回末尾迭代器(STL中红黑树中返回的是header)
  iterator end() 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(); }
插入/删除操作
  // insert/erase
  //有了红黑树提供的接口,完成插入/删除操作很方便
  typedef  pair<iterator, bool> pair_iterator_bool;
  pair<iterator,bool> insert(const value_type& x) {
    //insert_unique,不允许重复的值
    pair<typename rep_type::iterator, bool> p = t.insert_unique(x);
    //返回pair,第一个代表指向插入节点的迭代器,第二个代表插入是否成功
    return pair<iterator, bool>(p.first, p.second);
  }
  iterator insert(iterator position, const value_type& x) {
    typedef typename rep_type::iterator rep_iterator;
    return t.insert_unique((rep_iterator&)position, x);
  }
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  void insert(InputIterator first, InputIterator last) {
    t.insert_unique(first, last);
  }
#else
  void insert(const_iterator first, const_iterator last) {
    t.insert_unique(first, last);
  }
  void insert(const value_type* first, const value_type* last) {
    t.insert_unique(first, last);
  }
#endif /* __STL_MEMBER_TEMPLATES */
  /* 删除操作,也调用红黑树提供的erase即可
   * 根据指定位置删除、指定值删除、范围删除重载了不同的版本
   */
  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);
  }
  //这里也直接调用红黑树的clear函数,记住header没有被清除
  void clear() { t.clear(); }
其他
  // set operations:
  //以下也都是调用的红黑树提供的接口
  iterator find(const key_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);
  }
  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 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;
}

例子

#include <iostream>
#include <set>
using namespace std;
int main()
{
    set<int> s{1, 2, 3, 4, 5};

    set<int>::iterator first = s.begin();
    set<int>::iterator last = s.end();
    while(first != last)
    {
        cout << *first << endl;
        first++;
    }
    s.erase(s.begin(), s.end());
    cout << "size:" << s.size() << endl;

    s.insert(10);
    s.insert(9);


    set<int>::iterator ite1 = s.find(10);
    if(ite1 != s.end())
    {
        //*ite1 = 20;
        cout << "i find it" << endl;
    }
    else
        cout << "not found" << endl;
    return 0;
}

针对关联式容器,我们应当使用其提供的find函数,而不应该使用stl中算法部分提供的find函数(顺序查找)。
当我们试图改变set的值时,编译会出错并提示向只读位置‘ite1.std::_Rb_tree_const_iterator<_Tp>::operator*<int>()’赋值

小结

本小节中我们阅读了set容器的几乎全部源码,可以发现它只是将STL中的红黑树进行了一层封装,然后加上了自己的特性,所以实现的很简单,就连迭代器也是使用的红黑树中的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值