C++:list模拟实现
创始人
2024-11-15 16:36:33
0

hello,各位小伙伴,本篇文章跟大家一起学习《C++:list模拟实现》,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 !
如果本篇文章对你有帮助,还请各位点点赞!!!
在这里插入图片描述
话不多说,开始进入正题

🍁list的逻辑结构以及节点代码

在这里插入图片描述

是一个双指针带头链表,所以我选择用一个结构体ListNode来维护节点,如下:

// List的节点类 template struct ListNode {     ListNode(const T& val = T())         :_val(val)         ,_pPre(nullptr)         ,_pNext(nullptr)     {}     ListNode* _pPre;// 指向前一个结点     ListNode* _pNext;// 指向后一个节点     T _val;// 该结点的值 }; 

我对ListNode改一个名字:Node

typedef ListNode Node; typedef Node* PNode; 

🍁list类

🍃私有成员变量_pHead和私有成员函数CreateHead()

private:     void CreateHead()// 创建头节点并且初始化     {         _pHead = new Node();         _pHead->_pNext = _pHead;         _pHead->_pPre = _pHead;     }      PNode _pHead; 

🍃尾插函数和插入函数

尾插只是插入的其中一种方式,所以实现了插入函数,就能够实现尾插函数。
插入思路图解:在pos位置前插入值为val的节点

创建新节点值为value后; 使prev节点的_pNext指针指向newnode,newnode的节点的_pPre指向prev; 使cur节点的_pPre指针指向newnode,newnode的节点的_pNext指向cur; 最后返回iterator(newnode); 

在这里插入图片描述

itearator为迭代器,后面会实现

  • 插入
// 在pos位置前插入值为val的节点 iterator insert(iterator pos, const T& val) {     Node* cur = pos._pNode;     Node* newnode = new Node(val);     Node* prev = cur->_pPre;      // prev  newnode  cur     prev->_pNext = newnode;     newnode->_pPre = prev;     newnode->_pNext = cur;     cur->_pPre = newnode;          return iterator(newnode); } 
  • 尾插
void push_back(const T& val) { 	insert(end(), val);  } 

🍃构造函数

  • 无参构造
list(const PNode& pHead = nullptr) {     CreateHead();     /*_pHead = new Node();     _pHead->_pNext = _pHead;     _pHead->_pPre = _pHead;*/ } 
  • 带参构造(数值)
list(int n, const T& value = T()) {     CreateHead();     for (int i = 0; i < n; ++i)         push_back(value); } 
  • 带参构造(迭代器)
template  list(Iterator first, Iterator last) {     CreateHead();     while (first != last)     {         push_back(*first);         ++first;     } } 
  • 拷贝构造
list(const list& l) {     CreateHead();          // 复用带参构造(迭代器)     list temp(l.cbegin(), l.cend());  	// 与*this的头节点pHead交换指向     swap(temp); } 

🍃析构函数

clear()为其中的成员函数,功能:清理list中的数据

~list() {     clear();     delete _pHead;     _pHead = nullptr;      /*Node* cur = _pHead->_pNext;     Node* tmp = cur->_pNext;     while (cur != _pHead)     {         delete cur;         cur = tmp;         tmp = tmp->_pNext;     }     tmp = cur = nullptr;     _pHead->_pNext = _pHead;     _pHead->_pPre = _pHead;*/ } 

🍃迭代器模拟

逻辑上并不难,也许难理解于模板

//List的迭代器结构体 template struct ListIterator {     typedef ListNode* PNode;     typedef ListIterator Self;      ListIterator(PNode pNode = nullptr)         :_pNode(pNode)     {}      ListIterator(const Self& l)     {         _pNode = l._pNode;     }      T& operator*()     {         assert(_pNode != _pNode->_pNext);         return _pNode->_val;     }      T* operator->()     {         return &(*this);     }      Self& operator++()     {         _pNode = _pNode->_pNext;         return *this;     }      Self operator++(int)     {         PNode* tmp = _pNode;         _pNode = _pNode->_pNext;         return tmp;     }      Self& operator--()     {         _pNode = _pNode->_pPre;         return *this;     }      Self& operator--(int)     {         PNode* tmp = _pNode;         _pNode = _pNode->_pPre;         return tmp;     }      bool operator!=(const Self& l)     {         return _pNode != l._pNode;     }      bool operator==(const Self& l)     {         return !(*this != l);     }     PNode _pNode; }; 

这段代码定义了一个模板结构 ListIterator,用于表示List类的迭代器。让我们来解释模板声明部分:

template; 

这一行是模板声明,定义了一个模板类 ListIterator,它有三个模板参数:T、Ref 和 Ptr。让我们逐个解释这些参数的作用:

1.T: 这是一个模板参数,表示迭代器指向的元素类型。在使用 ListIterator 时,你需要提供实际的类型作为 T 的值。
2.Ref: 这也是一个模板参数,表示迭代器的引用类型。通常情况下,当你通过迭代器解引用(使用 * 运算符)时,你希望得到的是元素的引用类型。所以 Ref 通常被设定为 T&,表示引用类型为 T 的元素。
3.Ptr: 这是迭代器的指针类型。与 Ref 类似,当你通过迭代器解引用(使用 -> 运算符)时,你希望得到的是元素的指针类型。因此,通常情况下 Ptr 被设定为 T*,表示指针类型为 T 的元素。

通过将这些参数设定为模板参数,ListIterator 类可以适用于不同类型的元素,同时也可以提供不同的引用和指针类型。这样做使得 ListIterator 类更加灵活,能够适用于不同的使用场景。

  • 封装的意义
    将迭代器的实现从 List 类中分离出来,有几个重要的意义和优势:
  1. 模块化设计:通过将迭代器封装为单独的类,可以实现更模块化的设计。这意味着 List 类的实现与迭代器的实现可以分开,每个类都专注于自己的职责。这样的设计使得代码更易于理解、维护和测试。
  2. 可重用性:通过将迭代器设计为独立的类,可以在不同的容器类中重复使用相同的迭代器实现。例如,如果你有另一个类似于 List 的容器类,也需要迭代器来遍历其中的元素,你可以直接重用相同的迭代器实现,而无需重新编写。
  3. 灵活性:将迭代器设计为独立的类使得它们的实现更加灵活。你可以在迭代器类中添加额外的功能或改变迭代器的行为,而不会影响到容器类的实现。这样的设计使得容器和迭代器的职责分离,每个类可以独立地演化和改进。
  4. 通用性:独立的迭代器类可以设计成通用的,适用于多种容器类型。这意味着你可以为不同的容器类实现相同的迭代器接口,使得用户在使用不同的容器时无需学习不同的迭代器接口,提高了代码的一致性和可用性。

总的来说,将迭代器封装为独立的类使得代码更加模块化、可重用、灵活和通用,提高了代码的可维护性、可扩展性和可读性。

🍃list类中迭代器的使用

public:     typedef ListIterator iterator;     typedef ListIterator const_iterator; 
  • begin()和end()
// List Iterator iterator begin() {     return _pHead->_pNext; }  iterator end() {     return _pHead; }  const_iterator begin() const {     return _pHead->_pNext; }  const_iterator end() const {     return _pHead; } 
  • erase
    删除pos位置的节点,返回该节点的下一个位置
iterator erase(iterator pos) {     assert(pos._pNode != _pHead);     Node* Prev = pos._pNode->_pPre;     Node* Next = pos._pNode->_pNext;      delete pos._pNode;     Prev->_pNext = Next;     Next->_pPre = Prev;      return iterator(Next); } 

🍃List Modify

void push_back(const T& val) { insert(end(), val); } void pop_back() { erase(--end()); } void push_front(const T& val)  {      assert(!empty());     insert(begin(), val);  } void pop_front() { erase(begin()); } 

🍁全部代码

#pragma once #include #include using namespace std;  namespace My_List {     // List的节点类     template     struct ListNode     {         ListNode(const T& val = T())             :_val(val)             ,_pPre(nullptr)             ,_pNext(nullptr)         {}         ListNode* _pPre;         ListNode* _pNext;         T _val;     };       //List的迭代器类     template     struct ListIterator     {         typedef ListNode* PNode;         typedef ListIterator Self;          ListIterator(PNode pNode = nullptr)             :_pNode(pNode)         {}          ListIterator(const Self& l)         {             _pNode = l._pNode;         }          T& operator*()         {             assert(_pNode != _pNode->_pNext);             return _pNode->_val;         }          T* operator->()         {             return &(*this);         }          Self& operator++()         {             _pNode = _pNode->_pNext;             return *this;         }          Self operator++(int)         {             PNode* tmp = _pNode;             _pNode = _pNode->_pNext;             return tmp;         }          Self& operator--()         {             _pNode = _pNode->_pPre;             return *this;         }          Self& operator--(int)         {             PNode* tmp = _pNode;             _pNode = _pNode->_pPre;             return tmp;         }          bool operator!=(const Self& l)         {             return _pNode != l._pNode;         }          bool operator==(const Self& l)         {             return !(*this != l);         }         PNode _pNode;     };       //list类     template     class list     {         typedef ListNode Node;         typedef Node* PNode;     public:         typedef ListIterator iterator;         typedef ListIterator const_iterator;     public:         ///         // List的构造         list(const PNode& pHead = nullptr)         {             CreateHead();             /*_pHead = new Node();             _pHead->_pNext = _pHead;             _pHead->_pPre = _pHead;*/         }          list(int n, const T& value = T())         {             CreateHead();             for (int i = 0; i < n; ++i)                 push_back(value);              /*int cnt = 0;             while (cnt < n)             {                 PNode _first = new Node(value);                 PNode tmp = _pHead->_pPre;                 tmp->_pNext = _first;                 _first->_pPre = tmp;                 _first->_pNext = _pHead;                 _pHead->_pPre = _first;                 ++cnt;             }*/         }          template          list(Iterator first, Iterator last)         {             CreateHead();             while (first != last)             {                 push_back(*first);                 ++first;             }              /*while (first != last)             {                 PNode _first = new Node(*first);                 PNode tmp = _pHead->_pPre;                 tmp->_pNext = _first;                 _first->_pPre = tmp;                 _first->_pNext = _pHead;                 _pHead->_pPre = _first;                 ++first;             }*/         }          list(const list& l)         {             CreateHead();             list temp(l.cbegin(), l.cend());             swap(temp);              /*iterator first = l._pHead->_pNext;             iterator last = l._pHead;             while (first != last)             {                 PNode _first = new Node(*first);                 PNode tmp = _pHead->_pPre;                 tmp->_pNext = _first;                 _first->_pPre = tmp;                 _first->_pNext = _pHead;                 _pHead->_pPre = _first;                 ++first;             }*/         }          list& operator=(const list l)         {             CreateHead();              swap(l);             return *this;             /*iterator first = l._pHead->_pNext;             iterator last = l._pHead;             while (first != last)             {                 PNode _first = new Node(*first);                 PNode tmp = _pHead->_pPre;                 tmp->_pNext = _first;                 _first->_pPre = tmp;                 _first->_pNext = _pHead;                 _pHead->_pPre = _first;                 ++first;             }             return *this;*/         }          ~list()         {             clear();             delete _pHead;             _pHead = nullptr;              /*Node* cur = _pHead->_pNext;             Node* tmp = cur->_pNext;             while (cur != _pHead)             {                 delete cur;                 cur = tmp;                 tmp = tmp->_pNext;             }             tmp = cur = nullptr;             _pHead->_pNext = _pHead;             _pHead->_pPre = _pHead;*/         }           ///         // List Iterator         iterator begin()         {             return _pHead->_pNext;         }          iterator end()         {             return _pHead;         }          const_iterator begin() const         {             return _pHead->_pNext;         }          const_iterator end() const         {             return _pHead;         }           ///         // List Capacity         size_t size()const         {             Node* cur = _pHead->_pNext;             size_t cnt = 0;             while (cur != _pHead)             {                 ++cnt;                 cur = cur->_pNext;             }             return cnt;         }          bool empty()const         {             return size() == 0;         }                    // List Access         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;         }                    // List Modify         void push_back(const T& val) { insert(end(), val); }         void pop_back() { erase(--end()); }         void push_front(const T& val)          {              assert(!empty());             insert(begin(), val);          }         void pop_front() { erase(begin()); }         // 在pos位置前插入值为val的节点         iterator insert(iterator pos, const T& val)         {             Node* cur = pos._pNode;             Node* newnode = new Node(val);             Node* prev = cur->_pPre;              // prev  newnode  cur             prev->_pNext = newnode;             newnode->_pPre = prev;             newnode->_pNext = cur;             cur->_pPre = newnode;                          return iterator(newnode);         }          // 删除pos位置的节点,返回该节点的下一个位置         iterator erase(iterator pos)         {             assert(pos._pNode != _pHead);             Node* Prev = pos._pNode->_pPre;             Node* Next = pos._pNode->_pNext;              delete pos._pNode;             Prev->_pNext = Next;             Next->_pPre = Prev;              return iterator(Next);         }          void clear()         {             iterator cur = begin();             while (cur != end())             {                 cur = erase(cur);             }             _pHead->_pNext = _pHead;             _pHead->_pPre = _pHead;         }          void swap(list& l)         {             /*list tmp = l;             l = *this;             *this = tmp;*/              PNode tmp = _pHead;             _pHead = l._pHead;             l._pHead = tmp;         }      private:         void CreateHead()         {             _pHead = new Node();             _pHead->_pNext = _pHead;             _pHead->_pPre = _pHead;         }          PNode _pHead;     }; }; 

你学会了吗?
好啦,本章对于《C++:list模拟实现》的学习就先到这里,如果有什么问题,还请指教指教,希望本篇文章能够对你有所帮助,我们下一篇见!!!

如你喜欢,点点赞就是对我的支持,感谢感谢!!!

请添加图片描述

相关内容

热门资讯

Windows下Rust Op... 首发于Enaium的个人博客安装Chocolatey首先我们需要安装Chocolatey࿰...
深入探索:使用PHP开发保利威... 深入探索:使用PHP开发保利威Polyv云点播服务器API对接实践(一&...
实验篇(7.2) 04. 映射...   【简介】由于服务器的IP是内网地址,所以无法从公网直接访问服务器。要想远程访问服务...
GPT-4o mini一手测评... 在性能方面,GPT-4o mini 在 MMLU 上的得分为 82%,在 LMSYS 排行榜的聊天方...
Relying upon ci... Relying upon circular references is discouraged an...
关于unity下载安卓SDK模... 在使用Unity进行安卓应用开发时,有时会遇到下载安卓SDK模块失败并提示“Valid...
Unity_物体轮廓外发光 Shader实现Unity中物体轮廓外发光效果,效果如图上述效果分两个pass实现&#...
Unity矩阵入门—Matri... 最近在看矩阵,顺路记录一下复习吧1.矩阵变换- 平移向量矩阵转换在计算机图形学和游戏开...
【JVM】类加载器和双亲委派模... 什么是类加载器如果想要了解什么是类加载器就需要清楚一个Java文件是如何运行的。我们可以看下图&#x...
Unity实战问题--Load... int displayProgress = 0;int toProgress = 0...