folly->set_sorted_vector

* 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值