当前位置: 首页 > news >正文

一文学会c++list

文章目录

  • list简介
  • list接口
  • 迭代器失效
  • 🚩模拟实现

list简介

1,list是可以在常数时间复杂度任何位置随意插入的序列式容器,可以双向迭代
2,底层是双向链表结构,每个节点都是独立的,通过前后指针链接
3,相比vector,list随机插入更快,但是要访问随机元素更复杂,需要线性时间开销;还需要额外空间开销(保存前后指针);

list接口

和前文的string,vector接口一致,这里就不赘述了,无非多了头插头删
vector讲解

迭代器失效

与前文的vector一样,如果指针指向当前位置被释放,再访问就会崩溃

#include <iostream>
#include <list>
using namespace std;
int main()
{int a[] = {4, 5, 6};list<int> l1(a, a + sizeof(a) / sizeof(int));auto it = l1.begin();while(it!=l1.end()){cout << *it;//l1.erase(it);//it++;//错误it = l1.erase(it);//正确}return 0;
}

🚩模拟实现

#include <iostream>
namespace jib {template<class T>struct ListNode{ListNode(const T& val = T()):_prev(nullptr),_next(nullptr),_val(val){}ListNode<T>* _prev;ListNode<T>* _next;T _val;};template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T> Pnode;typedef ListIterator<T, Ref, Ptr> self;Pnode* _node;ListIterator(Pnode* pnode = nullptr):_node(pnode){}ListIterator(const self& l):_node(l._node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}self& operator++(){_node=_node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(self& l) const{return _node != l._node;}bool operator==(self& l) const{return !(*this!=l);}};template<class T>class list {typedef ListNode<T> Node;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;list(){CreateNode();}list(int n, const T& value = T()){CreateNode();for(int i=0;i<n;i++){push_back(value);}}template <class Iterator>list(Iterator first, Iterator last){CreateNode();while (first != last){push_back(*first);++first;}}list(const list<T>& l){CreateNode();list<T> tmp(l.begin(),l.end());this->swap(tmp);}list<T>& operator=(const list<T> l){this->swap(l);return *this;}~list(){clear();delete _phead;_phead = nullptr;}///////////////////////////////////////////////////////////////// List Iteratoriterator begin(){return iterator(_phead->_next);}iterator end(){return iterator(_phead);}const_iterator begin() const{return const_iterator(_phead->_next);}const_iterator end() const{return const_iterator(_phead);}///////////////////////////////////////////////////////////////// List Capacitysize_t size()const{size_t sz = 0;Node* p = _phead->_next;while (p != _phead){sz++;p = p->_next;}return sz;}bool empty()const{return size() == 0;}////////////////////////////////////////////////////////////// List AccessT& front(){access(!empty());return _phead->_next->_val;}const T& front()const{access(!empty());return _phead->_next->_val;}T& back(){access(!empty());return _phead->_prev->_val;}const T& back()const{access(!empty());return _phead->_prev->val;}////////////////////////////////////////////////////////////// List Modifypublic:void push_back(const T& val) { insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T& val){ insert(begin(), val); }void pop_front() { erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* newnode = new Node(val);Node* cur=pos._node;newnode->_prev = cur->_prev;newnode->_next = cur;cur->_prev->_next = newnode;cur->_prev = newnode;return iterator(newnode);}iterator erase(iterator pos){Node* cur = pos._node;Node* curnext = cur->_next;curnext->_prev = cur->_prev;cur->_prev->_next = curnext;delete cur;cur = nullptr;return iterator(curnext);}void clear(){iterator p = begin();while (!empty()){p = erase(p);}_phead->_next = _phead;_phead->_prev = _phead;}void swap(list<T>& l){std::swap(_phead, l._phead);}private:void CreateNode(){_phead = new Node;_phead->_next = _phead;_phead->_prev = _phead;}Node* _phead;};
}

先开辟节点类,再开辟迭代器类,再创建list类
注意 it用法:

struct Person {std::string name;int age;void print() { std::cout << name << ", " << age; }
};jib::list<Person> people;
people.push_back(Person{"Alice", 30});auto it = people.begin();
std::cout << it->name;  // 输出 "Alice"
it->age = 31;           // 修改年龄
it->print();            // 调用成员函数

调用 it.operator->(),返回 &_node->_val
编译器自动对结果应用 ->,变成== (&_node->_val)->name==

编译器自动省略了一个->

http://www.lryc.cn/news/600685.html

相关文章:

  • 激光雷达-相机标定工具:支持普通相机和鱼眼相机的交互式标定
  • 二叉搜索树(Binary Search Tree)详解与java实现
  • Linux 如何统计系统上各个用户登录(或者登出)记录出现的次数?
  • Android-三种持久化方式详解
  • 摘录-打造第二大脑
  • J2EE模式---表现层集成模式
  • C++ TAP(基于任务的异步编程模式)
  • Web后端进阶:springboot原理(面试多问)
  • React入门学习——指北指南(第五节)
  • JavaScript手录06-函数
  • 【RK3568 PWM 子系统(SG90)驱动开发详解】
  • 数据赋能(336)——技术平台——智能化运营
  • Java动态调试技术原理
  • 【RocketMQ】一分钟了解RocketMQ
  • 告别复杂配置!Spring Boot优雅集成百度OCR的终极方案
  • Windows 平台源码部署 Dify教程(不依赖 Docker)
  • 《C++ list 完全指南:从基础到高效使用》
  • Linux——线程同步
  • InvokeRepeating避免嵌套调用
  • C++编程学习(第16天)
  • 7月26日京东秋招第一场第一题
  • 【第二章-数据的表示和运算】
  • 基于java的在线教育平台管理系统、在线学习系统的设计与实现
  • 【机器学习-2】 | 决策树算法基础/信息熵
  • 背包问题及 LIS 优化
  • 【Ubuntu】发展历程
  • 排序算法,咕咕咕
  • 疏老师-python训练营-Day26函数专题1:函数定义与参数
  • Linux的生态与软件安装
  • 深入浅出学习 KNN 算法:从原理到数字识别实践