• GFStableList Adapter


        STL中,list的优点是插入、删除性能极佳(时间复杂度只需O(1)即可),而且非常重要的在删除节点后,其迭代器不失效,但list查找却不擅长。map由于其实现的数据结构为rb-tree,因此,其插入、删除以及查找的性能也都是非常不错的。如:插入、删除操作在多数情况下,可能只需要几个简单的数据交换、节点旋转即可达到目的,在这样情况下,时间复杂度也只有O(1)即可(当然,在最糟糕情况下,如插入、删除的时候产生上溯时,则时间复杂度最坏情况有可能达到2logN = O(logN),但由于rb-tree的性质原因,会产生最坏情况的机会也会比较少,而且大量试验证明,rb-tree的平均性能都是非常好的)。但是map容器在删除节点时,其迭代器是失效的

        但在项目开发(尤其是在游戏项目开发)中,像设计角色管理器、技能管理器、buff管理器等等时候,经常会遇到这样一个问题(说明:此处以角色管理器为例说明)如下:

        问题

        游戏中(或战场中吧),每一个角色对象都有一个唯一Id,那么,这些游戏中的对象该如何维护?

        解决

        见过有的项目中是将这些角色对象用map来维护的。看上去好像是比较理想,因为它查找非常方便,而且在实际当中,也的的确确是需要频繁根据唯一Id查找对应的角色对象。但用map有个问题,在这些对象更新时,有可能会遇到角色死亡的情况,此时该如何处理这个对象?是立即移除?是先打标记然后再在全部更新之后,再一次性全部移除?又或者是都不移除只是不再更新它而已?事实上,这些处理方案都不理想。事实上,用这个方案的项目,最终的结果是:因为没办法在更新时移时移除掉这些“垃圾”角色对象,性能好坏且不说,整个代码最后都显得比较乱。因为用户在到处查找使用时,都是小心查看取出来的该对象是否是有效的。

        另一种维护方案是使用list。该方案不必多说,数据组织与更新、移除都没啥大问题,就是查找效率不高。

        鉴于前面综述情况,特地设计一个容器适配器GFStableList,其功能类似list,但却具有map的查找性能,并且支持erase时,reverse_iterator参数。编码如下:

      1 #pragma once
      2 
      3 #include "src/Common/IncludeHeaders.h"
      4 
      5 /******************************************************************************
      6  * create   : (jacc.kim) [3-1-2016]
      7  * summary  : class GFStableList.
      8  * !!!note  : 01.该列表中的元素的"Id"是不可以重复的.
      9  *            02.该列表稳定、支持快速查找、类似std::list删除时迭代器有效.
     10  *            03.使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
     11  *               使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
     12  *               使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
     13 ******************************************************************************/
     14 template<typename TValue, typename TId>
     15 class GFStableList
     16 {
     17 public:
     18     typedef typename std::list<TValue>                          value_list;
     19     typedef typename value_list::value_type                     value_type;
     20     typedef typename value_list::pointer                        pointer;
     21     typedef typename value_list::const_pointer                  const_pointer;
     22     typedef typename value_list::reference                      reference;
     23     typedef typename value_list::const_reference                const_reference;
     24     typedef typename value_list::difference_type                difference_type;
     25     typedef typename value_list::size_type                      size_type;
     26     typedef typename value_list::iterator                       iterator;
     27     typedef typename value_list::const_iterator                 const_iterator;
     28     typedef typename value_list::reverse_iterator               reverse_iterator;
     29     typedef typename value_list::const_reverse_iterator         const_reverse_iterator;
     30 
     31     typedef typename TId                                        id_type;
     32     typedef typename std::function<id_type(const_reference)>    TGFvalueIdGetter;
     33     typedef typename std::function<void(const_reference)>       TGFvalueDeleter;
     34 
     35 public:
     36     GFStableList();
     37     explicit GFStableList(const TGFvalueIdGetter& getter);
     38     GFStableList(const TGFvalueIdGetter& getter, const TGFvalueDeleter& deleter);
     39     ~GFStableList();
     40 
     41     void                                setValueIdGetter(const TGFvalueIdGetter& getter);
     42     void                                setValueDeleter(const TGFvalueDeleter& deleter);
     43 
     44     // !!!note: only no exist items & valid items will be insert or push.
     45     const bool                          push_front(const_reference value);
     46     const bool                          push_back(const_reference value);
     47     iterator                            insert(const_iterator _where, const_reference value);
     48     iterator                            insert(const_iterator _where, const_iterator _first, const_iterator _last);
     49 
     50     iterator                            erase(const_reference value);
     51     iterator                            erase(const id_type& id);
     52     iterator                            erase(const_iterator _first, const_iterator _last);
     53     iterator                            erase(const_iterator _where);
     54     reverse_iterator                    erase(reverse_iterator _first, reverse_iterator _last);
     55     reverse_iterator                    erase(reverse_iterator _where);
     56     const_reverse_iterator              erase(const_reverse_iterator _first, const_reverse_iterator _last);
     57     const_reverse_iterator              erase(const_reverse_iterator _where);
     58     void                                clear();
     59     iterator                            find(const id_type& id);
     60     const_iterator                      find(const id_type& id) const;
     61 
     62     iterator                            begin();
     63     const_iterator                      begin() const;
     64     iterator                            end();
     65     const_iterator                      end() const;
     66 
     67     reverse_iterator                    rbegin();
     68     const_reverse_iterator              rbegin() const;
     69     reverse_iterator                    rend();
     70     const_reverse_iterator              rend() const;
     71 
     72     const_iterator                      cbegin() const;
     73     const_iterator                      cend() const;
     74     const_reverse_iterator              crbegin() const;
     75     const_reverse_iterator              crend() const;
     76 
     77     reference                           front();
     78     reference                           back();
     79     const_reference                     front() const;
     80     const_reference                     back() const;
     81 
     82     void                                pop_front();
     83     void                                pop_back();
     84 
     85     bool                                empty();
     86     size_type                           size();
     87 
     88 private:
     89     GFStableList(const GFStableList<TValue, TId>& listValues) = delete;
     90 
     91 private:
     92     typedef typename std::map<id_type, iterator>        id_value_map;
     93 
     94     void                                _clearValueList();
     95     void                                _clearMapping();
     96     iterator                            _locate(const_reference value);
     97     const_iterator                      _locate(const_reference value) const;
     98     iterator                            _locate(const id_type& id);
     99     const_iterator                      _locate(const id_type& id) const;
    100     const bool                          _isExisted(const id_type& id);
    101     const bool                          _isExisted(const_reference value);
    102     const id_type                       _getValueId(const_reference value);
    103 
    104 private:
    105     TGFvalueIdGetter                    m_IdGetter;
    106     TGFvalueDeleter                     m_ValueDeleter;
    107     value_list                          m_listValues;
    108     id_value_map                        m_mapMapping;
    109 
    110 };//template<typename TValue, typename TId> class GFStableList
    111 
    112 #include "src/Common/GFStableList.inl"
    GFStableList.h文件
      1 #include "src/Common/IncludeHeaders.h"
      2 
      3 ///////////////////////////////////////////////////////////////////////////////
      4 // template<typename TValue, typename TId> class GFStableList
      5 template<typename TValue, typename TId>
      6 GFStableList<TValue, TId>::GFStableList() : m_IdGetter    (nullptr)
      7                                           , m_ValueDeleter(nullptr)
      8                                           , m_listValues  ()
      9                                           , m_mapMapping  ()
     10 {
     11 
     12 }
     13 
     14 template<typename TValue, typename TId>
     15 GFStableList<TValue, TId>::GFStableList(const TGFvalueIdGetter& getter) : m_IdGetter    (getter)
     16                                                                         , m_ValueDeleter(nullptr)
     17                                                                         , m_listValues  ()
     18                                                                         , m_mapMapping  ()
     19 {
     20 
     21 }
     22 
     23 template<typename TValue, typename TId>
     24 GFStableList<TValue, TId>::GFStableList(const TGFvalueIdGetter& getter, const TGFvalueDeleter& deleter) : m_IdGetter    (getter)
     25                                                                                                         , m_ValueDeleter(deleter)
     26                                                                                                         , m_listValues  ()
     27                                                                                                         , m_mapMapping  ()
     28 {
     29 
     30 }
     31 
     32 template<typename TValue, typename TId>
     33 GFStableList<TValue, TId>::~GFStableList() {
     34     this->clear();
     35 }
     36 
     37 template<typename TValue, typename TId>
     38 void GFStableList<TValue, TId>::setValueIdGetter(const TGFvalueIdGetter& getter) {
     39     m_IdGetter = getter;
     40     //GFAssert(nullptr != m_IdGetter, "the id getter is nullptr.");
     41 }
     42 
     43 template<typename TValue, typename TId>
     44 void GFStableList<TValue, TId>::setValueDeleter(const TGFvalueDeleter& deleter) {
     45     m_ValueDeleter = deleter;
     46 }
     47 
     48 template<typename TValue, typename TId>
     49 const bool GFStableList<TValue, TId>::push_front(const_reference value) {
     50     return insert(begin(), value) != end();
     51 }
     52 
     53 template<typename TValue, typename TId>
     54 const bool GFStableList<TValue, TId>::push_back(const_reference value) {
     55     return insert(end(), value) != end();
     56 }
     57 
     58 template<typename TValue, typename TId>
     59 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::insert(const_iterator _where, const_reference value) {
     60     if (nullptr == value) {
     61         return end();
     62     }
     63 
     64     const auto id = _getValueId(value);
     65     if (_isExisted(id)) {
     66         return end();// 已经存在了.
     67     }
     68 
     69     auto iter = m_listValues.insert(_where, value);
     70     m_mapMapping[id] = iter;
     71     return iter;
     72 }
     73 
     74 template<typename TValue, typename TId>
     75 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::insert(const_iterator _where, const_iterator _first, const_iterator _last) {
     76     if (_first == end() || _first == _last) {
     77         return;
     78     }
     79     auto insert_pos = end();
     80     iterator tmpResult;
     81     id_type id;
     82     for (auto iter = _first; iter != _last; ++iter) {
     83         id = _getValueId(*iter);
     84         if (_isExisted(id)) {
     85             continue;// id is existed.
     86         }
     87         tmpResult = m_listValues.insert(_where, *iter);
     88         m_mapMapping[id] = tmpResult;
     89 
     90         if (insert_pos == end()) {
     91             insert_pos = tmpResult;
     92         }
     93     }
     94     return insert_pos;
     95 }
     96 
     97 template<typename TValue, typename TId>
     98 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_reference value) {
     99     auto iter = _locate(value);
    100     return erase(iter);
    101 }
    102 
    103 template<typename TValue, typename TId>
    104 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const id_type& id) {
    105     auto iter = _locate(id);
    106     return erase(iter);
    107 }
    108 
    109 template<typename TValue, typename TId>
    110 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_iterator _first, const_iterator _last) {
    111     if (_first == end()) {
    112         return end();
    113     }
    114     if (_first == begin() && _last == end()) {
    115         this->clear();
    116         return end();
    117     }
    118     iterator retIter = end();
    119     auto iter = _first;
    120     while (iter != _last && iter != end()) {
    121         retIter = this->erase(iter);
    122         iter = retIter;
    123     }
    124     return retIter;
    125 }
    126 
    127 template<typename TValue, typename TId>
    128 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_iterator _where) {
    129     if (_where == end()) {
    130         return end();
    131     }
    132     const auto id = _getValueId(*_where);
    133     m_mapMapping.erase(id);
    134     return m_listValues.erase(_where);
    135 }
    136 
    137 template<typename TValue, typename TId>
    138 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::erase(reverse_iterator _first, reverse_iterator _last) {
    139     if (_first == rend()) {
    140         return rend();
    141     }
    142     if (_first == rbegin() && _last == rend()) {
    143         this->clear();
    144         return rend();
    145     }
    146     reverse_iterator retIter = rend();
    147     auto iter = _first;
    148     while (iter != _last && iter != rend()) {
    149         retIter = this->erase(iter);
    150         iter = retIter;
    151     }
    152     return retIter;
    153 }
    154 
    155 template<typename TValue, typename TId>
    156 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::erase(reverse_iterator _where) {
    157     if (_where == rend()) {
    158         return rend();
    159     }
    160 
    161     auto ret_iter = _where; // 返回值.
    162     ++ret_iter;
    163 
    164     const auto id = _getValueId(*_where.base());
    165     this->erase(id);
    166 
    167     return ret_iter;
    168 }
    169 
    170 template<typename TValue, typename TId>
    171 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::erase(const_reverse_iterator _first, const_reverse_iterator _last) {
    172     if (_first == rend()) {
    173         return rend();
    174     }
    175     if (_first == rbegin() && _last == rend()) {
    176         this->clear();
    177         return rend();
    178     }
    179     const_reverse_iterator retIter = rend();
    180     auto iter = _first;
    181     while (iter != _last && iter != rend()) {
    182         retIter = this->erase(iter);
    183         iter = retIter;
    184     }
    185     return retIter;
    186 }
    187 
    188 template<typename TValue, typename TId>
    189 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::erase(const_reverse_iterator _where) {
    190     if (_where == rend()) {
    191         return rend();
    192     }
    193 
    194     auto ret_iter = _where; // 返回值.
    195     ++ret_iter;
    196 
    197     const auto id = _getValueId(*_where.base());
    198     this->erase(id);
    199 
    200     return ret_iter;
    201 }
    202 
    203 template<typename TValue, typename TId>
    204 void GFStableList<TValue, TId>::clear() {
    205     _clearValueList();
    206     _clearMapping();
    207 }
    208 
    209 template<typename TValue, typename TId>
    210 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::find(const id_type& id) {
    211     return _locate(id);
    212 }
    213 
    214 template<typename TValue, typename TId>
    215 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::find(const id_type& id) const {
    216     return _locate(id);
    217 }
    218 
    219 template<typename TValue, typename TId>
    220 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::begin() {
    221     return m_listValues.begin();
    222 }
    223 
    224 template<typename TValue, typename TId>
    225 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::begin() const {
    226     return m_listValues.begin();
    227 }
    228 
    229 template<typename TValue, typename TId>
    230 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::end() {
    231     return m_listValues.end();
    232 }
    233 
    234 template<typename TValue, typename TId>
    235 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::end() const {
    236     return m_listValues.end();
    237 }
    238 
    239 template<typename TValue, typename TId>
    240 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::rbegin() {
    241     return m_listValues.rbegin();
    242 }
    243 
    244 template<typename TValue, typename TId>
    245 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::rbegin() const {
    246     return m_listValues.rbegin();
    247 }
    248 
    249 template<typename TValue, typename TId>
    250 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::rend() {
    251     return m_listValues.rend();
    252 }
    253 
    254 template<typename TValue, typename TId>
    255 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::rend() const {
    256     return m_listValues.rend();
    257 }
    258 
    259 template<typename TValue, typename TId>
    260 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::cbegin() const {
    261     return m_listValues.cbegin();
    262 }
    263 
    264 template<typename TValue, typename TId>
    265 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::cend() const {
    266     return m_listValues.cend();
    267 }
    268 
    269 template<typename TValue, typename TId>
    270 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::crbegin() const {
    271     return m_listValues.crbegin();
    272 }
    273 
    274 template<typename TValue, typename TId>
    275 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::crend() const {
    276     return m_listValues.crend();
    277 }
    278 
    279 template<typename TValue, typename TId>
    280 typename GFStableList<TValue, TId>::reference GFStableList<TValue, TId>::front() {
    281     return m_listValues.front();
    282 }
    283 
    284 template<typename TValue, typename TId>
    285 typename GFStableList<TValue, TId>::reference GFStableList<TValue, TId>::back() {
    286     return m_listValues.back();
    287 }
    288 
    289 template<typename TValue, typename TId>
    290 typename GFStableList<TValue, TId>::const_reference GFStableList<TValue, TId>::front() const {
    291     return m_listValues.front();
    292 }
    293 
    294 template<typename TValue, typename TId>
    295 typename GFStableList<TValue, TId>::const_reference GFStableList<TValue, TId>::back() const {
    296     return m_listValues.end();
    297 }
    298 
    299 template<typename TValue, typename TId>
    300 void GFStableList<TValue, TId>::pop_front() {
    301     if (this->empty()) {
    302         return;
    303     }
    304     auto iter = this->begin();
    305     const auto id = _getValueId(*iter);
    306     this->erase(id);
    307 }
    308 
    309 template<typename TValue, typename TId>
    310 void GFStableList<TValue, TId>::pop_back() {
    311     if (this->empty()) {
    312         return;
    313     }
    314     auto riter = this->rbegin();
    315     const auto id = _getValueId(*riter);
    316     this->erase(id);
    317 }
    318 
    319 template<typename TValue, typename TId>
    320 bool GFStableList<TValue, TId>::empty() {
    321     return m_listValues.empty();
    322 }
    323 
    324 template<typename TValue, typename TId>
    325 typename GFStableList<TValue, TId>::size_type GFStableList<TValue, TId>::size() {
    326     return m_listValues.size();
    327 }
    328 
    329 template<typename TValue, typename TId>
    330 void GFStableList<TValue, TId>::_clearValueList() {
    331     if (nullptr != m_ValueDeleter) {
    332         auto iter = m_listValues.begin();
    333         auto iterend = m_listValues.end();
    334         for (; iter != iterend; ++iter) {
    335             m_ValueDeleter(*iter);
    336         }
    337     }
    338     m_listValues.clear();
    339 }
    340 
    341 template<typename TValue, typename TId>
    342 void GFStableList<TValue, TId>::_clearMapping() {
    343     m_mapMapping.clear();
    344 }
    345 
    346 template<typename TValue, typename TId>
    347 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::_locate(const_reference value) {
    348     const auto id = m_IdGetter(value);
    349     return _locate(id);
    350 }
    351 
    352 template<typename TValue, typename TId>
    353 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::_locate(const_reference value) const {
    354     const auto id = m_IdGetter(value);
    355     return _locate(id);
    356 }
    357 
    358 template<typename TValue, typename TId>
    359 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::_locate(const id_type& id) {
    360     auto iter = m_mapMapping.find(id);
    361     if (iter == m_mapMapping.end()) {
    362         return end();
    363     }
    364     return iter->second;
    365 }
    366 
    367 template<typename TValue, typename TId>
    368 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::_locate(const id_type& id) const {
    369     auto iter = m_mapMapping.find(id);
    370     if (iter == m_mapMapping.end()) {
    371         return end();
    372     }
    373     return iter->second;
    374 }
    375 
    376 template<typename TValue, typename TId>
    377 const bool GFStableList<TValue, TId>::_isExisted(const id_type& id) {
    378     auto iter = m_mapMapping.find(id);
    379     return iter != m_mapMapping.end();
    380 }
    381 
    382 template<typename TValue, typename TId>
    383 const bool GFStableList<TValue, TId>::_isExisted(const_reference value) {
    384     auto id = _getValueId(value);
    385     return _isExisted(id);
    386 }
    387 
    388 template<typename TValue, typename TId>
    389 typename const GFStableList<TValue, TId>::id_type GFStableList<TValue, TId>::_getValueId(const_reference value) {
    390     return m_IdGetter(value);
    391 }
    GFStableList.inl文件
  • 相关阅读:
    技术人员的找工之路(1
    技术人员的找工之路(3)
    Endian的由来
    android平台开发笔记1Spinner不能在sub activity中使用
    谈谈Groupon的成功
    线程安全的同步读写类的模板设计
    项目管理文件package.json
    10个每个开发人员都应该知道的强大JavaScript 解构技术
    绿色下载站上线了(MVC +Telerik开源控件)
    我开发的新浪微博应用“微词典”通过审核,欢迎朋友们试用,多多建议!
  • 原文地址:https://www.cnblogs.com/tongy0/p/5622329.html
Copyright © 2020-2023  润新知