欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > c++:list模拟实现

c++:list模拟实现

2024/11/29 21:36:43 来源:https://blog.csdn.net/weixin_67645591/article/details/143630424  浏览:    关键词:c++:list模拟实现

一、模拟实现list

要模拟实现list,必须要熟悉list的底层结构以及其接口的含义,大家可以看我关于list接口的博客c++:list-CSDN博客

1.1 list成员变量

list是一个双向带头链表,我们在定义成员变量时应该先定义出list单个的节点的类型。

1.1.1 list节点

    // List的节点类template<class T>struct ListNode{//默认构造    T()是一个匿名对象ListNode(const T& val = T()):_pPre(nullptr),_pNext(nullptr),_val(val){}ListNode<T>* _pPre;//指向上一个节点ListNode<T>* _pNext;//指向下一个节点T _val;             //节点的数据};

 在c++中class 和struct 的主要区别就是struct 中的成员变量和成员函数的默认访问权限是public,而class中的成员变量和成员函数的默认访问权限是private,这里直接用struct更方便。

1.1.2 list的成员变量

class List{typedef ListNode<T> Node;typedef Node* PNode;private:PNode _pHead;size_t _size = 0;
}

 这里我们把节点类型重命名为Node,又把节点的指针重命名为PNode。List的成员变量只有一个头节点的指针和节点的数量。(List底层是一个带头双向链表

1.2 list的默认成员函数

 1.2.1 默认构造

 public:///// List的构造//void CreateHead();//PNode _pHead;void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;_size = 0;}list(){CreateHead();}

1.2.2 构造函数

1.2.2.1 list中包含n个值为val的元素
        list(int n, const T& value = T()){CreateHead();int i = n;while (i--){push_back(value);}}

 1.2.2.2 用迭代器区间初始化list

        template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first!=last){push_back(*first);++first;}}

 1.2.3 拷贝构造

list(const list<T>& lt){CreateHead();// 用l中的元素构造临时的temp,然后与当前对象交换list<T> temp(lt.begin(), lt.end());this->swap(temp);}void swap(list<T>& l){std::swap(l._pHead, _pHead);std::swap(l._size, _size);}

1.2.4 赋值运算符重载

        list<T>& operator=(list<T> lt){swap(lt);return *this;}void swap(list<T>& l){std::swap(l._pHead, _pHead);std::swap(l._size, _size);}

 1.2.5 析构函数

        ~list(){clear();delete _pHead;_pHead = nullptr;}void clear(){iterator it = begin();while (it != end()){//不用++防止迭代器失效it=erase(it);}_size = 0;_pHead = nullptr;}

1.3 list capacity

        size_t size()const{return _size;}bool empty()const{return _size == 0;}

1.4 list 迭代器

正反向迭代器和const版本,反向迭代器是依靠正向迭代器实现,迭代器是通过对节点的指针进行封装,通过代码实现你想要的结果。

1.4.1 正向迭代器

    template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;//typedef ListIterator<T, T&, T*> iterator;//typedef ListIterator<T, const T&, const T&> const_iterator;public:ListIterator(PNode pNode = nullptr){_pNode = pNode;}Ref operator*(){return _pNode->_val;}Ptr 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 l._pNode != _pNode;}bool operator==(const Self& l){return l._pNode == _pNode;}PNode _pNode;};

 1.4.2 begin,cbegin,end,cend,rbegin,rend,crbegin,crend

        // List Iteratorpublic:typedef ListNode<T> Node;typedef Node* PNode;typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;   typedef ListReverseIterator<iterator,T, T&, T*> reverse_iterator;typedef ListReverseIterator<iterator,T, const T&, const T*> const_reverse_iterator;iterator begin(){return _pHead->_pNext;}iterator end(){return _pHead;}const_iterator begin()const{return _pHead->_pNext;}const_iterator end()const{return _pHead;}// ListreverseIteratorreverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin()const{return reverse_iterator(end());}const_reverse_iterator rend()const{return reverse_iterator(begin());}

 1.4.3 反向迭代器

template<class iterator, class T, class Ref, class Ptr>
struct ListReverseIterator
{
public:typedef ListReverseIterator<iterator,T, Ref, Ptr> Self;ListReverseIterator(iterator it):_it(it){}Ref operator*(){//解引用不影响迭代器iterator tmp = _it;return *--tmp;}Ptr operator->(){return &(operator*());}Self& operator++(){--_it;return *this;}Self operator++(int){Self tmp = _it--;return tmp;}Self& operator--(){++_it;return *this;}Self& operator--(int){Self tmp = --_it;return tmp;}bool operator!=(const Self& l){return _it!= l._it;}bool operator==(const Self& l){return _it == l._it;}private:iterator _it;
};

1.5 list Modify

这里的erase和insert要返回一个迭代器来防止迭代器失效的问题。

        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* tmp = pos._pNode;Node* prev = tmp->_pPre;newNode->_pNext = tmp;tmp->_pPre = newNode;newNode->_pPre = prev;prev->_pNext = newNode;_size++;return pos;}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){Node* tmp = pos._pNode;Node* tail = tmp->_pNext;Node* prev = tmp->_pPre;delete tmp;tail->_pPre = prev;prev->_pNext = tail;_size--;return iterator(tail);}

1.6 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的难点主要在迭代器的封装,反向迭代器的实现,和模板。

蟹蟹观看!点赞!关注!收藏!评论!一键三连!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com