[C++STL]C++实现list容器
生活随笔
收集整理的這篇文章主要介紹了
[C++STL]C++实现list容器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
代碼如下:
#pragma once #include <iostream> using namespace std;template<typename T> struct ListNode {T _data;ListNode<T> *_next;ListNode<T> *_prev;ListNode(const T & val = T()) :_data(val), _next(nullptr), _prev(nullptr) {}; };//template<typename T> //struct ListIterator //{ // typedef ListNode<T> Node; // typedef ListIterator<T> Self; // Node *_node; // // ListIterator(Node * node = nullptr) :_node(node) {} // // // //但是該操作并不方便,通過解引用再獲取對象值。 // /*以上的操作支持內置類型的基本操作,但是并不能滿足當結點存儲的內置類型的操作, // 當對對象解引用時,是返回的結點的_data,但是這個_data是一個對象, // 也就并非能得到內置類型的值。*it得到的是對象,再通過.來獲得對象的屬性值。 // 例如: // struct A // { // int _a; // A(int a = 0):_a(a){} // }; // // 使用時: // List<A> lst; // List<A>::iterator it = lst.begin(); // cout<<(*it)._a<<endl; // // */ // T &operator*() // { // return _node->_data; // } // // // //在STL庫中的迭代器可以直接通過->_a來獲取,迭代器是一個對象, // //怎么可以通過->來獲取自定義類型的屬性呢?我們就必須重載->來實現。 // //就是it->獲得自定義類型對象的地址, // //再通過->就可以獲得自定義類型對象的指定的值it->->_a // // 只是在C++會進行優化,省略了其中的一個->。 // // 下面是實現第一個->的代碼 例如: List<A> lst; List<A>::iterator it = lst.begin(); cout << it->_a << endl; // // // T *operator->() // { // return &(_node->_data) // } // // Self & operator++() // { // _node = _node->_next; // return *this; // } // // Self operator++(int) // { // Self tmp(_node); // _node = _node->_next; // return tmp; // } // // Self &operator--() // { // _node = _node->prev; // return *this; // } // // Self operator--(int) // { // Self tmp(_node); // _node = _node->prev; // return tmp; // } // // bool operator ==(const Self &s) // { // return _node == s._node; // } // // bool operator!=(const Self &s) // { // return _node != s._node; // } //};//template<typename T> //struct ConstListIterator //{ // typedef ListNode<T> Node; // typedef ConstListIterator<T> Self; // Node * _node; // ConstListIterator(Node *node = nullptr) :_node(node) {} // // ConstListIterator(const Self &s):node(s._node){} // // Self & operator++() // { // _node = _node->_next; // return *this; // } // // Self operator++(int) // { // Self tmp(_node); // _node = _node->_next; // return tmp; // } // // Self &operator--() // { // _node = _node->prev; // return *this; // } // // Self operator--(int) // { // Self tmp(_node); // _node = _node->prev; // return tmp; // } // // bool operator ==(const Self &s) // { // return _node == s._node; // } // // bool operator!=(const Self &s) // { // return _node != s._node; // } // // const T&operator*() // { // return _node->_data; // } // // const T*operator->() // { // return &(_node->_data); // } // //};//上面是iterator 和 const_iterator 的分開實現, //但是STL庫中實現并不是這樣子的,我們發現兩個迭代器類型只是類中兩個成員函數的返回值不一樣而已。 //其他代碼邏輯都是一樣的,所以我們可以通過多加兩個模板類型來解決這個問題,讓他們成為一個類,只是類型有所差別。 //在原來的迭代器中將模板改為template<class T, class Ref, class Ptr> T為普通類型,Ref為引用類型,Ptr為指針類型。template<typename T, typename Ref, typename Ptr> struct ListIterator {typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;Node *_node;ListIterator(Node *node = nullptr) :_node(node) {}ListIterator(const Self &s) : _node(s._node) {}Self & operator++(){_node = _node->_next;return *this;}Self operator++(int){Self tmp(_node);_node = _node->_next;return tmp;}Self &operator--(){_node = _node->_prev;return *this;}Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}Ref operator*(){return _node->_data;}Ptr operator->(){return &(_node->_data);}bool operator!=(const Self &s){return _node != s._node;}bool operator==(const Self &s){return _node == s._node;} };template<typename T> class List { public:typedef ListNode<T> Node;typedef ListIterator<T, T &, T *> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;/*typedef ListIterator<T> iterator;iterator begin(){return iterator(_header->_next);}iterator end(){return iterator(_header);}typedef ConstListIterator<T> const_iterator;const_iterator cbegin() const{return const_iterator(_header->_next);}const_iterator cend() const{return const_iterator(_header);}*///上面是由于iterator 和 const_iterator 的分開實現,所以要這樣寫。//下面是iterator 和 const_iterator 合在一起后的寫法。iterator begin(){return iterator(_header->_next);}iterator end(){return iterator(_header);}const_iterator cbegin() const{return const_iterator(_header->_next);}const_iterator cend() const{return const_iterator(_header);}List() :_header(new Node()){_header->_next = _header->_prev = _header;}List(int n, const T&val = T()) :_header(new Node()){_header->_next = _header->_prev = _header;for (size_t i = 0; i < n; i++){push_back(val);}}template<typename inputIterator>List(inputIterator first, inputIterator last) :_header(new Node()){_header->_next = _header->_prev = _header;while (first != last){push_back(*first);++first;}}//拷貝構造函數,現代寫法List(List<T> &l) :_header(new Node()){_header->_next = _header->_prev = _header;List<T> tmp(l.begin(), l.end());swap(tmp);}//交換兩個對象的頭結點void swap(List<T> &l){Node *tmp = l._header;l._header = this->_header;this->_header = tmp;}/*利用了拷貝構造函數創建新空間,然后再交換他們的頭結點,tmp離開函數就會自動釋放了*/List<T> &operator = (List<T> tmp){swap(tmp);return *this;}void push_back(const T &val){Node *tail = _header->_prev;Node *newNode = new Node(val);tail->_next = newNode;newNode->_prev = tail;newNode->_next = _header;_header->_prev = newNode;}void clear(){if (_header != nullptr){Node *cur = _header->_next;while (cur != _header){Node *next = cur->_next;delete[] cur;cur = nullptr;cur = next;}}}size_t size() const{int sz = 0;Node *cur = _header->_next;while (cur != _header){++sz;cur = cur->_next;}return sz;}iterator erase(iterator pos){if (pos != end()){Node *next = pos._node->_next;Node *prev = pos._node->_prev;prev->_next = next;next->_prev = prev;delete[] pos._node;return iterator(next);}return pos;}void insert(iterator pos, const T &val){Node * newNode = new Node(val);Node *prev = pos._node->_prev;Node *cur = pos._node;prev->_next = newNode;newNode->_prev = prev;newNode->_next = cur;cur->_prev = newNode;}void push_front(const T& val){insert(begin(), val);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}~List(){clear();delete _header;_header = nullptr;} private:Node *_header; };template<typename T> void PrintFor(List<T> &lst) {for (auto &e : lst){cout << e << " ";}cout << endl; }測試代碼如下:
#include <iostream> #include "List.h" using namespace std;struct A {int _a;A(int a = 0) :_a(a) {}; };int main() {List<int> lst;List<int> lst2(3, 1);string str = "12345";List<char> lst3(str.begin(), str.end());lst.push_back(1);lst.push_back(2);lst.push_back(3);lst.push_back(4);List<int>::iterator it = lst.begin();while (it != lst.end()){cout << *it << " ";++it;}cout << endl;List<A> lst4;lst4.push_back(1);lst4.push_back(2);lst4.push_back(3);lst4.push_back(4);List<A>::iterator it1 = lst4.begin();while (it1 != lst4.end()){cout << it1->_a << " ";++it1;}cout << endl;PrintFor(lst2);List<int> lst5;lst5.push_back(1);lst5.push_back(2);lst5.push_back(3);lst5.push_back(4);lst5.push_back(5);List<int>::iterator it2 = lst5.begin();while (it2 != lst5.end()){if (*it2 % 2 == 0) it2 = lst5.erase(it2);else ++it2;}PrintFor(lst5);return 0; }測試結果:
總結
以上是生活随笔為你收集整理的[C++STL]C++实现list容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苏萨克氏症候群的症状
- 下一篇: [C++STL]C++实现stack容器