C++ 拥有自己的很多容器vector,list ,set ,map,queue,但是不少大神做了很多比较之后结论就是每一个容器都有自己适用的场景,在自己适用的场景下效率将变的很高,反之差,这几个容器虽然大致适用方式类似,但是缺多少存在一些不完美,有的不能索引,有的不方便遍历或插入,std::list已经算是比较平衡的一个容器了,但是他也没提供按索引访问,所以是时候实现了一个自己的模板了,是的没错,在C++开发中你需要一个像C#的List这样的强势集合,或者说容器模板,那么废话不多说,直接分享一下我以前项目中经过实战考研的我自己写的一个双向链表模板了
直接贴出完整实现代码实用案例:
案例用法:(未来将把对List高效的排序和分组以及去重也统统实现)
PBList<int> ggg; ggg.Add(1);//压入等效于RPush右侧压入 ggg.Add(2); ggg.Add(3); ggg.Add(4); int a; ggg.LPop(a);//左侧弹出 int &aa = ggg.Last();//取最后一个值 aa = 8;//改变最后一个值 int *ggh = ggg[2];//按索引取值 PBList<int>::queue_block * block = ggg.at(2);//安索引取值 //正向遍历输出 ggg.ForEach([](int index, int &val, PBList<int>::queue_block * p){ printf("%d", val); }); //移除该移除的 ggg.RemoveAll([](int &val, PBList<int>::queue_block * p){ return val == 2; });
实现文件:
#pragma once #ifndef PBLIST_H_ #define PBLIST_H_ #include <iostream> #include <mutex> template <typename T> class PBList{ private: int _size; public: struct queue_block { T val; queue_block *next;//指向下一个 queue_block *prev;//指向上一个 queue_block(const T & _val) { val = _val; next = NULL; } }; queue_block *first, *last; queue_block * at(uint32_t index){ uint32_t _half_size = _size / 2; queue_block *p = NULL; if (index <= _half_size) { ForEach([&p,index](int i, T &a, queue_block * ent){ if (i == index){ p = ent; return; } }); } else if (index > _half_size&&index < _size) { RForEach([&p,index](int i, T &a, queue_block * ent){ if (i == index){ p = ent; return; } }); } return p; } void remove(queue_block * tmp) { if (tmp->prev != NULL)tmp->prev->next = tmp->next; else first = tmp->next; if (tmp->next != NULL)tmp->next->prev = tmp->prev; else last = tmp->next; //架空tmp之后马上删除他释放之 delete tmp; _size--;//长度减小 } public: PBList() { first = last = NULL; _size = 0; } ~PBList() { queue_block * p = first; while (p != NULL) { queue_block *tmp = p; p = p->next; delete tmp; } } public: void RPush(const T &data) { if (_size == 0) { queue_block * tmp = new queue_block(data); first = last = tmp; } else { queue_block * cur = last; queue_block * tmp = new queue_block(data); tmp->prev = cur; last = tmp; cur->next = tmp; } _size++; } void LPush(const T &data)//等效于AddFirst { if (_size == 0) { queue_block * tmp = new queue_block(data); first = last = tmp; } else { queue_block * cur = first; queue_block * tmp = new queue_block(data); tmp->next = cur; first = tmp; cur->prev = tmp; } _size++; } bool LPop(T& data) { if (_size == 0) return false; if (_size == 1) { queue_block * cur = first; first = last = NULL; data = cur->val; delete cur; } else { queue_block * cur = first; first = cur->next;//first转而指向下一个 first->prev = NULL;//且指向后把上一个设为空 data = cur->val; delete cur; } _size--; return true; } bool RPop(T& data){ if (_size == 0) return false; if (_size == 1) { queue_block * cur = last; first = last = NULL; data = cur->val; delete cur; } else { queue_block * cur = last; last = cur->prev;//first转而指向下一个 last->next = NULL;//且指向后把上一个设为空 data = cur->val; delete cur; } _size--; return true; } void Add(const T &data){ RPush(data); } //根据index和size比较决定正向查还是反向查 T* operator [](uint32_t index) { queue_block * tmp = at(index); if (tmp == NULL)return NULL; else return &tmp->val; } T& First(){ return first->val; } T& Last(){ return last->val; } int Length(){ return _size; } //正向遍历 template<typename ForEachCallback> void ForEach(ForEachCallback callback){ queue_block * p = first; int index = 0; while (p != NULL) { queue_block *tmp = p; callback(index, p->val, tmp); p = p->next; index++; } } //反向遍历 template<typename ForEachCallback> void RForEach(ForEachCallback callback){ queue_block * p = last; int index = _size - 1; while (p != NULL) { queue_block *tmp = p; callback(index, p->val, tmp); p = p->prev; index--; } } //查询符合条件第一个对象,并返回对象和索引 template<typename CondionCallback> T* FindFirst(CondionCallback callback, int *resindex = NULL) { queue_block * p = first; int index = 0; while (p != NULL) { queue_block *tmp = p; if (callback(index, p->val) == true) { *resindex = index; return &p->val; } p = p->next; index++; } return NULL; } //查询符合条件最后一个对象,并返回对象和索引 template<typename CondionCallback> T* FindLast(CondionCallback callback, int *resindex = NULL) { queue_block * p = last; int index = _size - 1; while (p != NULL) { queue_block *tmp = p; if (callback(index, p->val) == true) { *resindex = index; return &p->val; } p = p->prev; index--; } return NULL; } //查询符合条件的所有对象 template<typename CondionCallback> PBList<T*> FindAll(CondionCallback callback){ PBList<T*> hh; queue_block * p = first; while (p != NULL) { queue_block *tmp = p; if (callback(index, p->val) == true) { hh.Add(&p->val); } p = p->next; } } //删除符合条件的所有对象 template<typename CondionCallback> int RemoveAll(CondionCallback callback) { queue_block * p = first; int count = 0; while (p != NULL) { queue_block *tmp = p; queue_block *next = p->next; if (callback(tmp->val, tmp) == true) { remove(tmp); count++; } p = next; } return count; } //删除指定索引的元素队列,根据index大小和size大小决定从哪一头 bool RemoveAt(int index) { queue_block* tmp = at(index); remove(tmp); return true; } }; #endif