当前位置:首页 » 《休闲阅读》 » 正文

C++第十二弹 -- STL之list模拟实现

12 人参与  2024年09月07日 10:07  分类 : 《休闲阅读》  评论

点击全文阅读


文章索引

前言模拟实现list1. ListNode节点类2. list的迭代器封装3. 反向迭代器4. list类的模拟实现测试代码 list的反向迭代器总结

前言

通过模拟实现可以让我们更加深刻的理解C++底层STL的实现逻辑, 本篇就对list的底层进行模拟实现.

博客主页: 酷酷学!!! 点击关注 共同进步!!!


正文开始

模拟实现list

要模拟实现list, 必须要熟悉list的底层结构以及其接口的含义, 通过上一篇的学习, 这些内容基本掌握之后, 现在我们来模拟实现list.

1. ListNode节点类

#pragma once#include<iostream>using namespace std;#include<assert.h>namespace my{//list的节点类template<class T>struct ListNode{ListNode(const T& val = T()): _prev(nullptr), _next(nullptr), _val(val){}ListNode<T>* _prev;ListNode<T>* _next;T _val;};

2. list的迭代器封装

list的迭代器迭代器有两种实现方式, 具体应根据容器底层数据结构的实现:1.原生态指针, 比如:vector2.将原生态指针进行封装, 因迭代器使用形式与指针完全相同,因此在自定义的类中必须实现以下方法:1.指针可以解引用,迭代器的类中必须重载operator*()2.指针可以通过->访问其所指空间成员,迭代器类中必须重载operator->()3.指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int)  至于operator--()/operator--(int)释放需要重载,根据具体的结构来抉择,  双向链表可以向前或者向后移动,所以需要重载,如果是forward_list就不需要重载--4.迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()
template<class T,class Ref,class Ptr>class ListIterator{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;//Ref 和 Ptr类型需要重新定义下,实现反向迭代器时需要用到public:typedef Ref Ref;typedef Ptr Ptr;//构造ListIterator(Node* node = nullptr): _node(node){}//具有指针类似行为Ref operator*(){return _node->_val;}Ptr operator->(){return &(operator*());}//迭代器支持移动Self& operator++(){_node = _node->_next;return *this;}Self operator++(int){Self temp(*this);_node = _node->_next;return temp;}Self& operator--(){_node = _node->_prev;return *this;}Self operator--(int){Self temp(*this);_node = _node->_prev;return temp;}//迭代器支持比较bool operator!=(const Self& l) const{return _node != l._node;}bool operator==(const Self & l) const{return _node == l._node;}Node* _node;};

3. 反向迭代器

//反向迭代器,迭代器复用template<class Iterator>class ReverseListIterator{//注意:此处typename的作用是明确的告诉编译器,Ref是Iterator类中的一个类型,//而不是静态成员变量,否则编译器编译时就不知道Ref是Iterator中的类型还是静态成员//变量,因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;//构造ReverseListIterator(Iterator it): _it(it){}//具有指针类似行为Ref operator*(){Iterator temp(_it);--temp;return *temp;}Ptr operator->(){return &(operator*());}//迭代器支持移动Self& operator++(){--_it;return *this;}Self& operator++(int){Self temp(*this);--_it;return *this;}Self& operator--(){++_it;return *this;}Self& operator--(int){Self temp(*this);++_it;return temp;}//迭代器支持比较bool operator!=(const Self& l) const{return _it != l._it;}bool operator==(const Self& l) const{return _it == l._it;}Iterator _it;};

4. list类的模拟实现

template<class T>class list{typedef ListNode<T> Node;public://正向迭代器typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, T*> const_iterator;//反向迭代器typedef ReverseListIterator<iterator> reverse_iterator;typedef ReverseListIterator<const_iterator> const_reverse_iterator;//List的构造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 _head;_head = nullptr;}//list的迭代器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);}reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}//List的容器相关size_t size() const{Node* cur = _head->_next;size_t count = 0;while (cur != _head){++count;cur = cur->_next;}return count;}bool empty() const{return _head->_next = _head;}void resize(size_t newsize, const T* data = T()){size_t oldsize = size();if (newsize <= oldsize){//将有效元素减少到newsizewhile (newsize < oldsize){pop_back();--oldsize;}}else{while (oldsize < newsize){push_back(data);++oldsize;}}}//list的元素访问操作//注意:List不支持operator[]T& front(){return _head->_next->_val;}const T& front() const{return _head->_next->_val;}T& back(){return _head->_prev->_val;}const T& back() const {return _head->_prev->_val;}//list的插入和删除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* pNewNode = new Node(val);Node* pCur = pos._node;//先将新节点插入pNewNode->_prev = pCur->_prev;pNewNode->_next = pCur;pNewNode->_prev->_next = pNewNode;pCur->_prev = pNewNode;return iterator(pNewNode);}//删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){//找到待删除的节点Node* pDel = pos._node;Node* pRet = pDel->_next;//将该节点从链表中拆下来并删除pDel->_prev->_next = pDel->_next;pDel->_next->_prev = pDel->_prev;delete pDel;return iterator(pRet);}void clear(){Node* cur = _head->_next;//采用头删除删除while (cur != _head){Node* next = cur->_next;delete cur;cur = next;}_head->_next = _head->_prev = _head;}void swap(my::list<T>& l){std::swap(_head, l._head);}private:void CreateHead(){_head = new Node;_head->_prev = _head;_head->_next = _head;}Node* _head;};}

测试代码

对构造函数进行测试

//对模拟实现的list进行测试//正向打印链表template<class T>void PrintList(const my::list<T>& l){auto it = l.begin();while (it != l.end()){cout << *it << " ";++it;}cout << endl;}//测试list的构造void Testmylist1(){my::list<int> l1;my::list<int> l2(10, 5);PrintList(l2);int array[] = { 1,2,3,4,5,6,7,8,9,0 };my::list<int> l3(array, array + sizeof(array) / sizeof(array[0]));PrintList(l3);my::list<int> l4(l3);PrintList(l4);l1 = l4;PrintList(l1);}

在这里插入图片描述

对头/尾插入删除进行测试

//PushBack()/PopBack()/PushFront()/PopFront()void Testmylist2(){//测试pushBack和PopBackmy::list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);PrintList(l);l.pop_back();l.pop_back();PrintList(l);l.pop_back();cout << l.size() << endl;//测试pushFront与popFrontl.push_front(1);l.push_front(2);l.push_front(3);PrintList(l);l.pop_front();l.pop_front();PrintList(l);l.pop_front();cout << l.size() << endl;}

在这里插入图片描述

测试指定位置插入删除

//测试insert和erasevoid Testmylist3(){int array[] = { 1,2,3,4,5 };my::list<int> l(array, array + sizeof(array) / sizeof(array[0]));auto pos = l.begin();l.insert(l.begin(), 0);PrintList(l);++pos;l.insert(pos, 2);PrintList(l);l.erase(l.begin());l.erase(pos);PrintList(l);//pos指向的节点已经被删除,pos迭代器失效cout << *pos << endl;auto it = l.begin();while (it != l.end()){it = l.erase(it);}cout << l.size() << endl;}

在这里插入图片描述

测试反向迭代器

//测试反向迭代器void Testmylist4(){int array[] = { 1,2,3,4,5 };my::list<int> l(array, array + sizeof(array) / sizeof(array[0]));auto rit = l.rbegin();while (rit != l.rend()){cout << *rit << " ";++rit;}cout << endl;const my::list<int> cl(l);auto crit = l.rbegin();while (crit != l.rend()){cout << *crit <<" ";++crit;}cout << endl;}

在这里插入图片描述

list的反向迭代器

我们知道, 反向迭代器的++就是正向迭代器的- -, 反向迭代器的- -就是正向迭代器的++, 因此反向迭代器的实现可以借助正向迭代器, 即: 返现迭代器内部可以包含一个正向迭代器, 对正向迭代器的接口进行包装即可.

//反向迭代器,迭代器复用template<class Iterator>class ReverseListIterator{//注意:此处typename的作用是明确的告诉编译器,Ref是Iterator类中的一个类型,//而不是静态成员变量,否则编译器编译时就不知道Ref是Iterator中的类型还是静态成员//变量,因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;//构造ReverseListIterator(Iterator it): _it(it){}//具有指针类似行为Ref operator*(){Iterator temp(_it);--temp;return *temp;}Ptr operator->(){return &(operator*());}//迭代器支持移动Self& operator++(){--_it;return *this;}Self& operator++(int){Self temp(*this);--_it;return *this;}Self& operator--(){++_it;return *this;}Self& operator--(int){Self temp(*this);++_it;return temp;}//迭代器支持比较bool operator!=(const Self& l) const{return _it != l._it;}bool operator==(const Self& l) const{return _it == l._it;}Iterator _it;};

总结

通过以上的实现,可以模拟出一个类似于list的数据结构,并且可以对其中的元素进行添加、删除、查找、等操作。这样就可以在不使用C++内置的list时,使用自己实现的List类来进行相同的操作。

感谢您的点赞与收藏!!!


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/156531.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1