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