1:list的模擬實現
1:鏈表的節點
對于list的模擬實現,我們需要先定義一個節點的類可以使用(class也可以使用struct)
// 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>
//T是節點儲存的數據類型,Ref是T的引用T&,Ptr是T的指針T*
struct ListIterator
{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;//注意Self的重命名是定義的迭代器自己typedef Ref reference; //為反向迭代器做鋪墊 typedef Ptr pointer;//為反向迭代器做鋪墊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(_pNode);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self operator--(int){Self tmp(_pNode);_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l) const{return _pNode != l._pNode;}bool operator==(const Self& l) const{return _pNode == l._pNode; }PNode _pNode;
};
為什么提供了三個模版參數,因為在對于迭代器自己操作中,可能需要返回T的引用或者T的地址,比如*和->的運算符重載。
在迭代器里面,本質上就是定義一個ListNode*<T> 的一個指針,來對鏈表進行操作。
3:鏈表的增刪查改
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;typedef Reverse_iterator<iterator> reverse_iterator;//反向迭代器typedef Reverse_iterator<const_iterator> const_reverse_iterator;//反向迭代器
public:///// 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();list<T> tmp(l.begin(), l.end());swap(tmp);}list<T>& operator=(const list<T> l){swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// List Iteratoriterator 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);}reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}///// List Capacitysize_t size()const{auto it = begin();size_t count = 0;while (it != end()){it++;count++;}return count;}bool empty()const{return _pHead->_pNext == _pHead;}// List AccessT& 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 Modifyvoid 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* pcur = pos._pNode;newnode->_pPre = pcur->_pPre;newnode->_pNext = pcur;pcur->_pPre->_pNext = newnode;pcur->_pPre = newnode;return iterator(newnode);}// 刪除pos位置的節點,返回該節點的下一個位置iterator erase(iterator pos){ assert(size()>0); Node* pcur = pos._pNode;Node* pret = pcur->_pNext;pcur->_pPre->_pNext = pcur->_pNext;pcur->_pNext->_pPre = pcur->_pPre;delete pcur;return iterator(pret);}void clear(){Node* 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);}
private:void CreateHead(){_pHead = new ListNode<T>; //這里是模版_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;}PNode _pHead;
};
1:list的構造
對于list的構造我們實現了四種構造方式,第一是直接構造一個空鏈表,第二是使用n個相同元素構造鏈表,第三是使用迭代器來構造鏈表,第四就是使用list本身構造鏈表,額外重載運算符=來實現鏈表。
2:list的迭代器在類中的返回
我們可以很直觀的看到迭代器在類中是返回的什么。
3:list的容量判斷
我們之間在類的內部使用迭代器便利鏈表來計算鏈表大小。
4:增刪操作
邏輯和以前對于鏈表的實現上大型不差,出了額外增加了幾個接口然后使用迭代器。
2:反向迭代器的實現
反向迭代器本質上就是正向迭代器的封裝
template<class Iterator>struct Reverse_iterator{public:
// 注意:此處typename的作用是明確告訴編譯器,Ref是Iterator類中的類型,而不是靜態成員變量
// 否則編譯器編譯時就不知道Ref是Iterator中的類型還是靜態成員變量
// 因為靜態成員變量也是按照 類名::靜態成員變量名 的方式訪問的typedef typename Iterator::reference Ref; // 從正向迭代器提取typedef typename Iterator::pointer Ptr;typedef Reverse_iterator<Iterator> Self;public:Reverse_iterator(Iterator it = nullptr) :_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 temp;}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;};