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文件

 

posted @ 2016-06-28 09:35  Jacc.Kim  阅读(197)  评论(0编辑  收藏  举报