wordpress中文cms主題模板seo綜合查詢愛站
文章索引
- 前言
- 模擬實(shí)現(xiàn)list
- 1. ListNode節(jié)點(diǎn)類
- 2. list的迭代器封裝
- 3. 反向迭代器
- 4. list類的模擬實(shí)現(xiàn)
- 測(cè)試代碼
- list的反向迭代器
- 總結(jié)
前言
通過模擬實(shí)現(xiàn)可以讓我們更加深刻的理解C++底層STL的實(shí)現(xiàn)邏輯, 本篇就對(duì)list的底層進(jìn)行模擬實(shí)現(xiàn).
博客主頁: 酷酷學(xué)!!! 點(diǎn)擊關(guān)注 共同進(jìn)步!!!
正文開始
模擬實(shí)現(xiàn)list
要模擬實(shí)現(xiàn)list, 必須要熟悉list的底層結(jié)構(gòu)以及其接口的含義, 通過上一篇的學(xué)習(xí), 這些內(nèi)容基本掌握之后, 現(xiàn)在我們來模擬實(shí)現(xiàn)list.
1. ListNode節(jié)點(diǎn)類
#pragma once
#include<iostream>
using namespace std;
#include<assert.h>namespace my
{//list的節(jié)點(diǎn)類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的迭代器
迭代器有兩種實(shí)現(xiàn)方式, 具體應(yīng)根據(jù)容器底層數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn):
1.原生態(tài)指針, 比如:vector
2.將原生態(tài)指針進(jìn)行封裝, 因迭代器使用形式與指針完全相同,
因此在自定義的類中必須實(shí)現(xiàn)以下方法:1.指針可以解引用,迭代器的類中必須重載operator*()2.指針可以通過->訪問其所指空間成員,迭代器類中必須重載operator->()3.指針可以++向后移動(dòng),迭代器類中必須重載operator++()與operator++(int)至于operator--()/operator--(int)釋放需要重載,根據(jù)具體的結(jié)構(gòu)來抉擇,雙向鏈表可以向前或者向后移動(dòng),所以需要重載,如果是forward_list就不需要重載--4.迭代器需要進(jìn)行是否相等的比較,因此還需要重載operator==()與operator!=()
template<class T,class Ref,class Ptr>class ListIterator{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;//Ref 和 Ptr類型需要重新定義下,實(shí)現(xiàn)反向迭代器時(shí)需要用到public:typedef Ref Ref;typedef Ptr Ptr;//構(gòu)造ListIterator(Node* node = nullptr): _node(node){}//具有指針類似行為Ref operator*(){return _node->_val;}Ptr operator->(){return &(operator*());}//迭代器支持移動(dòng)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. 反向迭代器
//反向迭代器,迭代器復(fù)用template<class Iterator>class ReverseListIterator{//注意:此處typename的作用是明確的告訴編譯器,Ref是Iterator類中的一個(gè)類型,//而不是靜態(tài)成員變量,否則編譯器編譯時(shí)就不知道Ref是Iterator中的類型還是靜態(tài)成員//變量,因?yàn)殪o態(tài)成員變量也是按照 類名::靜態(tài)成員變量名 的方式訪問的public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;//構(gòu)造ReverseListIterator(Iterator it): _it(it){}//具有指針類似行為Ref operator*(){Iterator temp(_it);--temp;return *temp;}Ptr operator->(){return &(operator*());}//迭代器支持移動(dòng)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類的模擬實(shí)現(xiàn)
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的構(gòu)造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中的元素構(gòu)造臨時(shí)的temp,然后與當(dāng)前對(duì)象交換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的容器相關(guān)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的節(jié)點(diǎn)iterator insert(iterator pos, const T& val){Node* pNewNode = new Node(val);Node* pCur = pos._node;//先將新節(jié)點(diǎn)插入pNewNode->_prev = pCur->_prev;pNewNode->_next = pCur;pNewNode->_prev->_next = pNewNode;pCur->_prev = pNewNode;return iterator(pNewNode);}//刪除pos位置的節(jié)點(diǎn),返回該節(jié)點(diǎn)的下一個(gè)位置iterator erase(iterator pos){//找到待刪除的節(jié)點(diǎn)Node* pDel = pos._node;Node* pRet = pDel->_next;//將該節(jié)點(diǎn)從鏈表中拆下來并刪除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;};
}
測(cè)試代碼
對(duì)構(gòu)造函數(shù)進(jìn)行測(cè)試
//對(duì)模擬實(shí)現(xiàn)的list進(jìn)行測(cè)試
//正向打印鏈表
template<class T>
void PrintList(const my::list<T>& l)
{auto it = l.begin();while (it != l.end()){cout << *it << " ";++it;}cout << endl;
}//測(cè)試list的構(gòu)造
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);
}
對(duì)頭/尾插入刪除進(jìn)行測(cè)試
//PushBack()/PopBack()/PushFront()/PopFront()
void Testmylist2()
{//測(cè)試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;//測(cè)試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;
}
測(cè)試指定位置插入刪除
//測(cè)試insert和erase
void 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指向的節(jié)點(diǎn)已經(jīng)被刪除,pos迭代器失效cout << *pos << endl;auto it = l.begin();while (it != l.end()){it = l.erase(it);}cout << l.size() << endl;
}
測(cè)試反向迭代器
//測(cè)試反向迭代器
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的反向迭代器
我們知道, 反向迭代器的++就是正向迭代器的- -, 反向迭代器的- -就是正向迭代器的++, 因此反向迭代器的實(shí)現(xiàn)可以借助正向迭代器, 即: 返現(xiàn)迭代器內(nèi)部可以包含一個(gè)正向迭代器, 對(duì)正向迭代器的接口進(jìn)行包裝即可.
//反向迭代器,迭代器復(fù)用template<class Iterator>class ReverseListIterator{//注意:此處typename的作用是明確的告訴編譯器,Ref是Iterator類中的一個(gè)類型,//而不是靜態(tài)成員變量,否則編譯器編譯時(shí)就不知道Ref是Iterator中的類型還是靜態(tài)成員//變量,因?yàn)殪o態(tài)成員變量也是按照 類名::靜態(tài)成員變量名 的方式訪問的public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;//構(gòu)造ReverseListIterator(Iterator it): _it(it){}//具有指針類似行為Ref operator*(){Iterator temp(_it);--temp;return *temp;}Ptr operator->(){return &(operator*());}//迭代器支持移動(dòng)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;};
完
總結(jié)
通過以上的實(shí)現(xiàn),可以模擬出一個(gè)類似于list的數(shù)據(jù)結(jié)構(gòu),并且可以對(duì)其中的元素進(jìn)行添加、刪除、查找、等操作。這樣就可以在不使用C++內(nèi)置的list時(shí),使用自己實(shí)現(xiàn)的List類來進(jìn)行相同的操作。
感謝您的點(diǎn)贊與收藏!!!