list的接口
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{template<class T>struct listnode {listnode* <T>_next;listnode* <T>_prev;T _data;listnode(const T& x = T()):_prev(nulllptr),_next(nullptr),_data(x){}};template<class T>struct _list_iterator{typedef listnode <T>node;typedef _list_iterator<T>self;node* _node;_list_iterator(node* n):_node(n){}self& operator++(){}self& operator--(){}self operator++(int){}self operator--(int){}bool operator!=(const self& s){}bool operator==(const self& s){}T& operator(){}};template <class T>class list{ typedef listnode <T>node;public:typedef _list_iterator<T> iterator;list(){empty_init();}void empty_init(){}iterator begin(){}iterator end(){}void clear(){}~list{}list(const list<T>& it){}void push_back(const T&x){}void push_front(const T& x){}void pop_back(){}void pop_front(){}void swap(list<T>& tmp){}list<T>& operator=(list<T>it){}iterator insert(iterator pos ,const T&x){}iterator erase(iterator pos){}private :node* _head;};}
迭代器前置++,前置–,后置++,后置–
self& operator++(){ _node= _node->next;return * this;}self& operator--(){_node = _node->_prev;return * this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}
迭代器重載等于,以及不等于,以及解引用訪問數據
bool operator!=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}T& operator*(){return _node->_data;}
鏈表的默認構造,以及尾插,獲取鏈表的頭和尾巴,以及測試尾插函數
list(){empty_init();}void empty_init(){_head = new node();_head->_prev = _head;_head->_next = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}void push_back(const T&x){node* newnode = new node(x);node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}
尾插測試,以及迭代器測試
void test1(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout <<*it << " ";it++;}}
const迭代器的實現
我們就可以新增兩個帶const的begin(),end(),權限平移就可以調動。
iterator begin() const{return _head->_next;}iterator end() const{return _head;}
如果我們要修改迭代器所指向位置的值呢??
我們應該如何模擬實現一個常量迭代器呢??
如果按照以下的方式,可以實現嗎??
所以我們應該怎么實現呢??
迭代器中的解引用函數,我們需要讓他的返回值不被修改,所以 這個函數的返回值加const 就好了,所以我們在實現一個類,這個類基本和普通迭代器的類一樣,只是在解引用函數上有區分。
template<class T>struct const_list_iterator{typedef listnode <T> node;typedef const_list_iterator<T> self;node* _node;const_list_iterator(node* n):_node(n){}self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->_prev;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator !=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}const T operator*(){return _node->_data;}};
這樣子,就實現了const 的迭代器,但是重新搞一個類好麻煩呀,于是有大佬就想出了在提供一個模板參數來解決這個問題
->運算符重載函數
我們可以想一下什么時候會用到->,當指針it指向的是結構體的話,我們可以訪問使用
it->data,來訪問數據,也可先對指針解引用*it,*it表示拿到這個結構體,然后使用.來訪問(*it).data;
T* operator->(){return &_node->_data;}
struct AA{int a1;int a2;AA(int _a1=0,int _a2=0):a1(_a1),a2(_a2){}};
測試->
void test3(){list<AA>res; res.push_back(AA(1,1));res.push_back(AA(2, 2));res.push_back(AA(3, 3));res.push_back(AA(4, 4));list<AA> ::iterator it = res.begin();while (it != res.end()){cout << it.operator->()->a1<<":" << it.operator->()->a2 << endl;it++;}}
這里有一個問題就是->訪問也是取數據,但取到的數據能修改嗎?這就面臨和解引用取數據同樣的問題。
我們現在需要做的是const迭代器的不能被將修改,普通的可以修改值
我發現這里和解引用那里不一樣的是,解引用那里是值不可被修改,這里是地址不可被修改
=運算符重載賦值
void swap(list<T>& tmp){std::swap(_head, tmp._head);}list<T>& operator=(list<T>it){swap(it);return *this;}
賦值函數測試
void test4(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret = res;list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}
拷貝構造函數
list(const list<T>& it){empty_init();for (auto e : it){push_back(e);}}
這里與賦值不一樣的地方是賦值的話,之前的空間不用放著也沒用,就在原空間操作了;拷貝構造是重新開的空間,然后將原來數據尾插到新空間
拷貝構造函數測試
void test5(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret(res);list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}
insert函數和earse函數
因為之前寫的雙向鏈表就是借鑒的這里,如果邏輯不清楚,可以去看一下雙向鏈表那一篇文章
(insert)
iterator insert(iterator pos ,const T&x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return newnode;}
(earse)
iterator erase(iterator pos){assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return next;}
這里insert函數迭代器不會失效,而earse函數迭代器會失效,最好earse完,給迭代器傳下一個位置的地址。
析構函數
void clear(){ iterator it = begin();while (it != end()){it = earse(it);//釋放完一個結點,返回下一個結點地址}}~list(){clear();//完成后只剩頭節點delete _head;//釋放頭節點_head = nullptr;//防止野指針cout<<"析構完成“<<endl;}
析構測試
void test8(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}res.~list();}
push_front函數,pop_back()函數,pop_front()函數
因為實現了insert和earse,所以這三個就簡單了。
void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}
注意這里的end()是最后一個數據的下一個位置,所以要先–
測試頭插
void test6(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.push_front(1000);list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}
測試頭刪和尾刪
void test7(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.pop_front();res.pop_back();list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}
測試這三個間接測試了insert和erase
源碼展示
list.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{template<class T>struct listnode{listnode<T>* _next;listnode<T>* _prev;T _data;listnode(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}};template<class T ,class res,class ptr>struct _list_iterator{ typedef listnode <T> node;typedef _list_iterator<T,res,ptr> self;node* _node;_list_iterator(node* n):_node(n){}self& operator++(){ _node= _node->_next;return * this;}self& operator--(){_node = _node->_prev;return * this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator !=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}res operator*(){return _node->_data;}ptr operator->(){return &_node->_data;}};template <class T>class list{typedef listnode <T> node;public:typedef _list_iterator<T,T&,T*> iterator;typedef _list_iterator<T,const T&,const T*> const_iterator;list(){empty_init();}void empty_init(){_head = new node();_head->_prev = _head;_head->_next = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}iterator erase(iterator pos){assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return next;}void clear(){ iterator it = begin();while (it != end()){it=erase(it);}}~list(){clear();delete _head;_head = nullptr;cout << "析構完成" << endl;}list(const list<T>& it){empty_init();for (auto e : it){push_back(e);}}void push_back(const T&x){node* newnode = new node(x);node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void swap(list<T>& tmp){std::swap(_head, tmp._head);}list<T>& operator=(list<T>it){swap(it);return *this;}iterator insert(iterator pos ,const T&x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return newnode;}private :node* _head;};struct AA{int a1;int a2;AA(int _a1 = 0, int _a2 = 0):a1(_a1), a2(_a2){}};void print_list(const list<AA>it){list<AA>::const_iterator res =it.begin();while (res!=it.end()){cout << res.operator->()->a1 << ":" << res->a2 << endl;res++;}}/* void test1(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout <<*it << " ";it++;}}*///void test2()//{// list<int>res;// res.push_back(1);// res.push_back(2);// res.push_back(3);// res.push_back(4);// print_list(res);////////////}/* void test3(){list<AA>res; res.push_back(AA(1,1));res.push_back(AA(2,2));res.push_back(AA(3, 3));res.push_back(AA(4, 4));print_list(res);}*//* void test4(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret = res;list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}*//* void test5(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret(res);list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}*//* void test6(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.push_front(1000);list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}*//* void test7(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.pop_front();res.pop_back();list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}*/void test8(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}res.~list();}}
.cpp
#include"list.h"
int main()
{zjw::test8();}