folly->set_sorted_vector

来源:互联网 发布:好用的日记本软件 编辑:程序博客网 时间:2024/06/01 10:38
* This header defines two classes that very nearly model * AssociativeContainer (but not quite).  These implement set-like and * map-like behavior on top of a sorted vector, instead of using * rb-trees like std::set and std::map. * * This is potentially useful in cases where the number of elements in * the set or map is small, or when you want to avoid using more * memory than necessary and insertions/deletions are much more rare * than lookups (these classes have O(N) insertions/deletions). */*这个头文件定义了两个相近的类,相协调的类,但不相等,在已排好的vector,实现行为像set,map的行为,而不是红黑树,这潜在的好处就是当set和map的元素比较小的时候,当你想避免使用更多的内存,而这的重要性比你插入/删除更多,比查找更少,这些类拥有O(N)现行复杂度的插入删除如果你对最小化使用内存有兴趣,那么这些类应该支持增长政策参数,不论我们什么时候插入元素,他都会被调用,然后你可以调用reserve(),根据现有的内存使用情况来分配新的内存*/ * In the interest of using these in conditions where the goal is to * minimize memory usage, they support a GrowthPolicy parameter, which * is a class defining a single function called increase_capacity, * which will be called whenever we are about to insert something: you * can then decide to call reserve() based on the current capacity() * and size() of the passed in vector-esque Container type.  An * example growth policy that grows one element at a time: * *    struct OneAtATimePolicy { *      template<class Container> *      void increase_capacity(Container& c) { *        if (c.size() == c.capacity()) { *          c.reserve(c.size() + 1); *        } *      } *    }; * *    typedef sorted_vector_set<int, *                              std::less<int>, *                              std::allocator<int>, *                              OneAtATimePolicy> *            OneAtATimeIntSet; * * Important differences from std::set and std::map: *   - insert() and erase() invalidate iterators and references *   - insert() and erase() are O(N) *   - our iterators model RandomAccessIterator *   - sorted_vector_map::value_type is pair<K,V>, not pair<const K,V>. *     (This is basically because we want to store the value_type in *     std::vector<>, which requires it to be Assignable.) */#pragma once#include <algorithm>#include <initializer_list>#include <iterator>#include <utility>#include <vector>#include <boost/operators.hpp>#include <boost/bind.hpp>//vs报错#include <boost/type_traits/is_same.hpp>namespace folly {//////////////////////////////////////////////////////////////////////namespace detail {  // This wrapper goes around a GrowthPolicy and provides iterator  // preservation(保存) semantics, but only if the growth policy is not the  // default (i.e. nothing).  template<class Policy>  struct growth_policy_wrapper : private Policy {    template<class Container, class Iterator>    Iterator increase_capacity(Container& c, Iterator desired_insertion)    {      typedef typename Container::difference_type diff_t;      diff_t d = desired_insertion - c.begin();      Policy::increase_capacity(c);      return c.begin() + d;    }  };/*这个类用来封装增长分配的政策,明显政策这里是具有弹性的,针对上面的OneAtATimePolicy  有几点疑问:它用私有继承,我能理解毕竟一个容器是用来用的,不是开源让后人盖楼,从OneAtATimePolicy    用size()和capacity()我能推断出,这是以标准库容器作为参数,  未知:为什么参数是将要插入的位置;为什么没有插入动作(下面解答),却返回插入位置的指针*/  template<>  struct growth_policy_wrapper<void> {    template<class Container, class Iterator>    Iterator increase_capacity(Container&, Iterator it) {      return it;    }  };  /*这个全特化,看起来就像为空政策做的准备  */  /*   * This helper returns the distance between two iterators if it is   * possible to figure it out without messing up the range   * (i.e. unless they are InputIterators).  Otherwise this returns   * -1.   */  /*这个助手返回两个迭代器的距离,前提是没有把这两个的范围搞错,例如两个数相等*/  template<class Iterator>  int distance_if_multipass(Iterator first, Iterator last) {    typedef typename std::iterator_traits<Iterator>::iterator_category categ;    if (boost::is_same<categ,std::input_iterator_tag>::value)        return -1;    return std::distance(first, last);  }  //这里把输入溜迭代器除外,应该不能进行减操作  template<class OurContainer, class Vector, class GrowthPolicy>  typename OurContainer::iterator  insert_with_hint(OurContainer& sorted,                   Vector& cont,                   typename OurContainer::iterator hint,                   typename OurContainer::value_type&& value,                   GrowthPolicy& po)  {    const typename OurContainer::value_compare& cmp(sorted.value_comp());    if (hint == cont.end() || cmp(value, *hint)) {      if (hint == cont.begin()) {        po.increase_capacity(cont, cont.begin());        //OneAtATimePolicy就是看看有地方没,下面才是真正的插入动作        return cont.insert(cont.begin(), std::move(value));      }      /*这是一种特殊情况,所插位置所在值既比既比value大,且他还插在头部*/      if (cmp(*(hint - 1), value)) {        hint = po.increase_capacity(cont, hint);        return cont.insert(hint, std::move(value));      }      /*他想插在末尾,且前面的值比他小        或者说他满足第二个条件,后面的值比它大,这时再满足这个条件        就又可以不用再调整顺序了      */      return sorted.insert(std::move(value)).first;      //把上面的vector理解为data members就好    }    if (cmp(*hint, value)) {      if (hint + 1 == cont.end() || cmp(value, *(hint + 1))) {        typename OurContainer::iterator it =          po.increase_capacity(cont, hint + 1);        return cont.insert(it, std::move(value));      }    }    //当插入的值比 将插入位置所在值大,又分了两种情况,最后一个,注意左闭右开    //或者正好将插入位置的后一个位置所在值比插入值大,这样也可以不用重新排序了    // Value and *hint did not compare, so they are equal keys.    return hint;//如果都不符合了,就返回这个迭代器  }}///////////////////////////////////////////////////////////////////////** * A sorted_vector_set is a container similar to std::set<>, but * implemented as as a sorted array with std::vector<>. * * @param class T               Data type to store * @param class Compare         Comparison function that imposes a *                              strict weak ordering over instances of T * @param class Allocator       allocation policy * @param class GrowthPolicy    policy object to control growth * * @author Aditya Agarwal <aditya@fb.com> * @author Akhil Wable    <akhil@fb.com> * @author Jordan DeLong  <delong.j@fb.com> */template<class T,         class Compare      = std::less<T>,         class Allocator    = std::allocator<T>,         class GrowthPolicy = void>class sorted_vector_set  : boost::totally_ordered1<      sorted_vector_set<T,Compare,Allocator,GrowthPolicy>    , detail::growth_policy_wrapper<GrowthPolicy> >{  typedef std::vector<T,Allocator> ContainerT;  detail::growth_policy_wrapper<GrowthPolicy>&  get_growth_policy() { return *this; }public:  typedef T       value_type;  typedef T       key_type;  typedef Compare key_compare;  typedef Compare value_compare;  typedef typename ContainerT::pointer                pointer;  typedef typename ContainerT::reference              reference;  typedef typename ContainerT::const_reference        const_reference;  /*   * XXX: Our normal iterator ought to also be a constant iterator   * (cf. Defect Report 103 for std::set), but this is a bit more of a   * pain.   */  typedef typename ContainerT::iterator               iterator;  typedef typename ContainerT::const_iterator         const_iterator;  typedef typename ContainerT::difference_type        difference_type;  typedef typename ContainerT::size_type              size_type;  typedef typename ContainerT::reverse_iterator       reverse_iterator;  typedef typename ContainerT::const_reverse_iterator const_reverse_iterator;  explicit sorted_vector_set(const Compare& comp = Compare(),                             const Allocator& alloc = Allocator())    : m_(comp, alloc)  {}  template<class InputIterator>  explicit sorted_vector_set(      InputIterator first,      InputIterator last,      const Compare& comp = Compare(),      const Allocator& alloc = Allocator())    : m_(comp, alloc)  {    // This is linear if [first, last) is already sorted (and if we    // can figure out the distance between the two iterators).    insert(first, last);  }  explicit sorted_vector_set(      std::initializer_list<value_type> list,      const Compare& comp = Compare(),      const Allocator& alloc = Allocator())    : m_(comp, alloc)  {    insert(list.begin(), list.end());  }  key_compare key_comp() const { return m_; }  value_compare value_comp() const { return m_; }  iterator begin()                      { return m_.cont_.begin();  }  iterator end()                        { return m_.cont_.end();    }  const_iterator begin() const          { return m_.cont_.begin();  }  const_iterator end() const            { return m_.cont_.end();    }  reverse_iterator rbegin()             { return m_.cont_.rbegin(); }  reverse_iterator rend()               { return m_.cont_.rend();   }  const_reverse_iterator rbegin() const { return m_.cont_.rbegin(); }  const_reverse_iterator rend() const   { return m_.cont_.rend();   }  void clear()                  { return m_.cont_.clear();    }  size_type size() const        { return m_.cont_.size();     }  size_type max_size() const    { return m_.cont_.max_size(); }  bool empty() const            { return m_.cont_.empty();    }  void reserve(size_type s)     { return m_.cont_.reserve(s); }  void shrink_to_fit()          { m_.cont_.shrink_to_fit();   }  size_type capacity() const    { return m_.cont_.capacity(); }  std::pair<iterator,bool> insert(const value_type& value) {    return insert(value_type(value));  }  std::pair<iterator,bool> insert(value_type&& value) {    iterator it = lower_bound(value);    if (it == end() || value_comp()(value, *it)) {      it = get_growth_policy().increase_capacity(m_.cont_, it);      return std::make_pair(m_.cont_.insert(it, std::move(value)), true);    }    return std::make_pair(it, false);  }  iterator insert(iterator hint, const value_type& value) {    return insert(hint, value_type(value));  }  iterator insert(iterator hint, value_type&& value) {    return detail::insert_with_hint(*this, m_.cont_, hint, std::move(value),      get_growth_policy());  }

到这里,最让我头疼的就是插入的判断条件。

0 0
原创粉丝点击