文章目录

  • list
    • list的介绍
    • list的优缺点
  • list的迭代器失效问题
  • 实现的接口
    • 节点部分
    • 迭代器部分
    • list部分
  • 代码实现

list

list的介绍

list的文档介绍

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高 效。
  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。
  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间
    开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)

其实list就是数据结构中的双向循环链表, 实现思路我之前有写过
带头双向循环链表

STL中的list和双向链表大体的思路一样,只是多了迭代器和模板等c++的特性,所以下面大部分代码我都直接复用了以前过的代码

list的优缺点

优点:
1.list的存储方式不像vector是线性的连续的,它是链式的存储空间,只保持了逻辑上的连续,所以不需要考虑扩容的问题,更加有效的利用空间
2.因为是链式的存储方式,所以不需要像vector一样插入删除时需要挪动数据,所以插入删除时的时间复杂度为O(1)

缺点:
1.因为是链式结构,所以不支持下标的随机访问,导致很多算法用起来十分麻烦


list的迭代器失效问题

list的迭代器失效问题主要就体现在erase上,因为list的空间并不是连续的,而是通过prev和next两个指针来找到前后的结点,而一旦erase掉一个结点,此时再对那个节点使用++或者–就会导致迭代器失效的报错问题,因为节点已经被释放,自然就无法通过自身的prev和next访问到前后的结点。


实现的接口

节点部分

迭代器部分

list的迭代器不再像之前的一样直接用指针来模拟,而是封装了一个指向节点类的指针,所以我们还需要重载迭代器的运算符,来保证它能够像指针一样使用

__list_node<T>* _next;
__list_node<T>* _prev;
T _data;
__list_node(const T& data = T());
typedef __list_node<T> Node;
typedef __list_iterator<T, Ref, Ptr> Self;
Node* _node;
__list_iterator(Node* node);
Ref operator*();
Ptr operator->();
Self& operator++();
Self operator++(int);
Self& operator--();
Self operator--(int);
bool operator==(const Self& it);
bool operator!=(const Self& it);

list部分

默认成员函数部分

list() : _head(new Node);
list(const list<T>& l) : _head(new Node);
list<T>& operator=(list<T> l);
~list();

迭代器部分

typedef __list_node<T> Node;
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;

容量部分

size_t size() const;
bool empty()const;

元素访问部分

T& front();
const T& front()const;
T& back();
const T& back()const;

修改部分

void clear();
void pop_front();
void push_front(const T& val);
void pop_back() ;
void push_back(const T& val);
iterator erase(iterator pos);
iterator insert(iterator pos, const T& val);
void swap(list<T>& l);

私有成员

Node* _head; //头结点

代码实现

#pragma once
#include<cassert>namespace lee
{//节点template<class T>struct __list_node{__list_node<T>* _next;__list_node<T>* _prev;T _data;__list_node(const T& data = T()): _data(data), _next(nullptr), _prev(nullptr){}};//迭代器//使用三个模板参数来实现代码复用,可以根据传的参数来同时实现const_iterator和iterator//为了能够模拟迭代器,需要重载对应的运算符template<class T, class Ref, class Ptr>struct __list_iterator{typedef __list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> Self;Node* _node;__list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}/*这里其实使用了多个->,例如有一个对象it,it->_data就等价于it.operator->()->_data。这里重载的部分就返回了指向对象的指针,(*it的类型)->_data,然后再通过那个指针访问数据。如果存在嵌套的类,这里则会一直递归调用对象中重载的->,直到取到数据,但是这里因为编译器优化 所以只需要写一次就行*/Ptr operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self operator++(int){Self temp(*this);++(*this);return temp;}Self& operator--(){_node = _node->_prev;return *this;}Self operator--(int){Self temp(*this);--(*this);return temp;}bool operator==(const Self& it){return _node == it._node;}bool operator!=(const Self& it){return _node != it._node;}};template<class T>class list{public:typedef __list_node<T> Node;typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;/*------------------------------------------------------------默认成员函数部分Member functions------------------------------------------------------------*/list() : _head(new Node){_head->_next = _head;_head->_prev = _head;}list(const list<T>& l) : _head(new Node){_head->_next = _head;_head->_prev = _head;for (auto it : l){push_back(it);}}list<T>& operator=(list<T> l){swap(l);return *this;}~list(){clear();delete _head;_head = nullptr;}/*------------------------------------------------------------迭代器部分Iterators:------------------------------------------------------------*/iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const {return const_iterator(_head);}/*------------------------------------------------------------修改部分Modifiers:------------------------------------------------------------*/void swap(list<T>& l){std::swap(_head, l._head);}iterator insert(iterator pos, const T& val){assert(pos._node != nullptr);Node* cur = pos._node;Node* prev = cur->_prev;Node* newNode = new Node(val);prev->_next = newNode;cur->_prev = newNode;newNode->_next = cur;newNode->_prev = prev;return iterator(newNode);}iterator erase(iterator pos){         assert(_head->_next != _head);Node* cur = pos._node;Node* next = cur->_next;next->_prev = cur->_prev;cur->_prev->_next = next;delete cur;return iterator(next);}//和数据结构里面实现的一样,可以直接复用insert和erasevoid push_back(const T& val){insert(end(), val);//head}void pop_back() { erase(--end()); //head->prev}void push_front(const T& val){insert(begin(), val);//head->next;}void pop_front(){erase(begin());//head->next;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}/*------------------------------------------------------------元素访问部分Element access:------------------------------------------------------------*/T& front(){return _head->_next->_data;}const T& front()const{return _head->_next->_data;}T& back(){return _head->_prev->_data;}const T& back()const{return _head->_prev->_data;}/*------------------------------------------------------------容量部分Capacity------------------------------------------------------------*/size_t size()const{size_t count = 0;auto it = begin();while (it != end()){count++;it++;}return count;}bool empty()const{return _head->_next == _head;}private:Node* _head;};
}

C++ STL : 模拟实现STL中的list类相关推荐

  1. C++ STL : 模拟实现STL中的关联式容器unordered_map/unordered_set

    目录 unordered_map/unordered_set unordered_map/unordered_set与map/set的区别 底层哈希桶的改造 仿函数 Key值的获取方法 hash(ke ...

  2. C++ STL : 模拟实现STL中的容器适配器stack和queue

    目录 什么是容器适配器 stack stack的文档介绍-(来自cplusplus) stack的实现 queue queue的文档介绍-(来自cplusplus) queue的实现 什么是容器适配器 ...

  3. C++ STL : 模拟实现STL中的vector类

    文章目录 vector vector的介绍 vector的优缺点 实现时需要注意的细节问题 1. Capacity增长问题 2. memset等函数来带的按字节拷贝问题 3. 深浅拷贝问题 4. 迭代 ...

  4. C++ STL : 模拟实现STL中的关联式容器map和set

    目录 关联式容器 键值对 底层红黑树的改造 仿函数 红黑树的迭代器 完整代码 set set的文档介绍 set的实现 map map的文档介绍 map的实现 operator[] 完整代码 multi ...

  5. C++ STL : 模拟实现STL中的容器适配器priority_queue

    目录 priority_queue 文档介绍 实现思路 思路 仿函数 实现 priority_queue 文档介绍 文档介绍 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含 ...

  6. C++ STL : 模拟实现STL中的string类

    string的文档介绍 string是表示字符序列的类 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性. string类是使用c ...

  7. 【C++】vector的模拟实现@STL —— 迭代器失效问题

    vector的模拟实现@STL 1. (constructor) & (destructor) 2. 一系列基本接口 2.1 size & capacity 2.2 [] 2.3 it ...

  8. 1/22 测试一(STL 模拟 贪心)C.(贪心,给出气球,输出最好成绩)Contest Balloons

    1/22 测试一(STL 模拟 贪心) C.(贪心,给出气球,输出最好成绩)Contest Balloons One tradition of ACM-ICPC contests is that a ...

  9. c++ 的 stl模板库_C ++中的标准模板库(STL)

    c++ 的 stl模板库 Standard Template Library (STL) is a collection of standard C++ template classes. It co ...

最新文章

  1. PNAS:张航课题组揭示人类为何“扭曲”概率信息
  2. 单片机模块学习之数码管
  3. python编程少儿游戏编程_少儿编程课堂|python – 用游戏学编程
  4. BOOST_MP11_VERSION宏用法的测试程序
  5. 加密算法—MD5、RSA、DES
  6. CentOS下Redis 2.2.14安装配置详解
  7. 9.29 csp-s模拟测试55 联+赛+题
  8. 使用web进行数据库管理
  9. 微软云存储更换品牌 免费空间将翻番达到15GB
  10. 如何在表格里做计算机统计表,如何运用Excel编制统计表并做一般数据分析?-excel统计怎么做,最简单的统计表格怎么做...
  11. python编写背单词程序
  12. java培训机构那个好点
  13. K2P padavan固件下宽带与IPTV融合
  14. boost库的安装和使用
  15. Python PEP8编码规范
  16. 手机裂脑纪:中国式审美还有救吗?
  17. cucumber Hooks @Before @After 不执行
  18. 微软pop3服务器,真算孤陋寡闻。。微软旗下的邮箱都支持POP3收发邮件了
  19. 《电磁场与电磁波》MATLAB 仿真实验
  20. 排序算法之冒泡排序代码

热门文章

  1. 元组-元组变量的常用操作
  2. SocketIO-nio
  3. java文件中有中文,在windows下因编码不一致,而导致编译失败的处理方法。
  4. python文件下载器代码_GitHub - applechi/pythonCollection: python代码集合(文件下载器、pdf合并、极客时间专栏下载、掘金小册下载、新浪微博爬虫等)...
  5. postman cookie设置_是时候抛弃Postman了,因为REST Client更香
  6. java B2B2C Springcloud电子商城系统-Spring Cloud常见问题与总结(四)
  7. org.hibernate.MappingException: entity class not found hbm可以解析,但是实体类不能解析...
  8. Unknown opcode
  9. Cisco 2960 交换机密码设置
  10. 洛谷 - P2770 航空路线问题(最大费用最大流+路径打印)