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

STL之list

list简单介绍

  1. list是STL的一个序列式容器,底层的实现是一个双向链表,每个节点有两个指针分别指向前一个元素和后一个元素
  2. list在任意位置的插入与删除元素的效率很高,但是它访问元素的效率就相对比较低,它不支持任意位置的访问

list与vector的对比

这里不介绍list的使用,因为它和vector大部分的接口是一样的,不了解vector的可以去看
STL之vector

不同点

  • 迭代器失效的问题:vector的迭代器在插入删除时都可能导致迭代器失效但是list在插入时迭代器是不会失效的
  • vector访问元素的效率很高它能快速访问任意位置的数据,但是其插入与删除元素的效率极低,而list刚好与之相反
  • 需要大量随时访问元素时优先考虑使用vector,而要求插入删除的效率更高时优先考虑list

list的模拟实现

需要的类模板

  1. ’节点类

    // List的节点类template<class T>struct ListNode{ListNode(const T& val = T()):_pPre(nullptr),_pNext(nullptr),_val(val){}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val;
    

    2.迭代器类

    //List的迭代器类template<class T, class Ref, class Ptr>class ListIteratortemplate<class T, class Ref, class Ptr>class ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;public:ListIterator(PNode pNode = nullptr): _pNode(pNode){}ListIterator(const Self& l): _pNode(l._pNode){}//运算符重载               T& operator*(){return _pNode->_val;}T* operator->(){return & _pNode->_val;}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tmp(*this);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){Self tmp(*this);_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return _pNode == l._pNode;}PNode _pNode;
    

    为了减少代码的冗余所以将 ListNode*,ListIterator<T, Ref, Ptr>,用typedef进行封装

    3.list类

    template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T&> const_iterator;private:void CreateHead(){_pHead = new Node;_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;}PNode _pHead;
    

同意为了减少代码的冗余所以用typedef进行封装

构造与析构

调用接口CreateHead()和push_back()很容易实现构造

 list(){CreateHead();}list(int n, const T& value = T()){CreateHead();for (int i = 0; i < n; ++i)push_back(value);}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){push_back(*first);++first;}}list(const list<T>& l){CreateHead();// 用l中的元素构造临时的temp,然后与当前对象交换list<T> temp(l.begin(), l.end());this->swap(temp);}list<T>& operator=(list<T> l){this->swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}

迭代器

两种迭代器运用函数的重载即可实现

iterator begin(){return iterator(_pHead->_pNext);}iterator end(){return iterator (_pHead);}const_iterator begin() const{return const_iterator ( _pHead->_pNext);}const_iterator end() const{return const_iterator (_pHead);}

容量

  size_t size()const{PNode cur = _pHead->_pNext;size_t count = 0;while (cur != _pHead){count++;cur = cur->_pNext;}return count;}bool empty()const{return _pHead->_pNext == _pHead;}

获取元素

返回相应值即可

 T& front(){return _pHead->_pNext->_val;}const T& front()const{return  _pHead->_pNext->_val;}T& back(){return _pHead->_pPre->_val;}const T& back()const{return _pHead->_pPre->_val;}

修改

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()); 

运用迭代器和insert()erase()接口

insert的实现

iterator insert(iterator pos, const T& val){Node* pNewNode = new Node(val);Node* pCur = pos._pNode;pNewNode->_pPre = pCur->_pPre;pNewNode->_pNext = pCur;pNewNode->_pPre->_pNext = pNewNode;pCur->_pPre = pNewNode;return iterator(pNewNode);}

首先创建一个的节点Node让它的向前指针指向pos节点的前一个节点,它的向后指针指向pos位置的节点

然后再让pos位置的前一个节点的向后的指针指向新的节点Node,pos位置的向前指针指向新节点Node即可

erase的实现

iterator erase(iterator pos){Node* pDel = pos._pNode;Node* pRet = pDel->_pNext;pDel->_pPre->_pNext = pDel->_pNext;pDel->_pNext->_pPre = pDel->_pPre;delete pDel;return iterator(pRet);}

首先保存被删除节点的指针用pDel保存,因为erase返回的是被删除节点的下一个节点的迭代器所以我们也要将其保存在pRet中,然后就就简单了,将被删节点的后一个节点的向前指针指向被删节点的前一个节点,将被删节点的前一个节点的向后指针指向被删除指针的后面一个节点即可。

void clear(){PNode cur = _pHead->_pNext;while (cur != _pHead){_pHead->_pNext = cur->_pNext;delete cur;cur = _pHead->_pNext;}_pHead->_pNext = _pHead->_pPre = _pHead;}void swap(list<T>& l){std::swap(_pHead, l._pHead);}

clear()遍历list删除即可,swap()用std的swap接口


http://www.mrgr.cn/news/33388.html

相关文章:

  • 写论文好痛苦
  • ODOO学习笔记(6):Odoo与Oracle ERP的区别
  • <tauri><websocket>tauri集成web端使用websocket实现数据通讯
  • MQ集群
  • 深入探索:Scrapy深度爬取策略与实践
  • 接口测试整体框架
  • c语言-数据类型
  • C++:数组与字符串
  • Git从了解到操作
  • 【homebrew安装】踩坑爬坑教程
  • Renesas R7FA8D1BH (Cortex®-M85) 生成4路PWM
  • 【ArcGIS微课1000例】0123:数据库中要素类批量转为shapefile
  • 数据结构之堆(优先级队列)
  • 2024/9/22周报
  • 【面经】查找中常见的树数据结构
  • 8. Data Member的绑定
  • 国产游戏技术能否引领全球【终稿】
  • CompletableFuture如何优雅处理异步任务超时!妙就完了
  • 国人卖家可折叠无线充电器发起TRO专利维权,功能相同可能侵权
  • 【深入学习Redis丨第六篇】Redis哨兵模式与操作详解
  • 图神经网络的新篇章:通用、强大、可扩展的图变换器
  • WebGL基础知识快速入门
  • 空栈压数 - 华为OD统一考试(E卷)
  • thinkphp 做分布式服务+读写分离+分库分表(分区)(后续接着写)
  • 【shell脚本4】Shell脚本学习--字符串和数组
  • 掌控历史:如何通过Git版本管理工具提升你的开发效率