list底层实现
list底层实现
_list_node
//创建 构造节点的类 struct _list_node { _list_node<T>* next; _list_node<T>* prve; T _val; _list_node(const T& val=T()) :next(nullptr) , prve(nullptr) ,_val(val) { } };
_list_iterator
template<class T , class Ref , class Ptr>//Ref Ptr 是可以很好的区分const与非const版本 //通过重命名 通过不同的命名 传过来的参数是不同的 struct _list_iterator { typedef _list_node<T> Node; //typedef _list_iterator<T, T&, T*> self;//这里要传 Ref 和 Ptr 不然const版本没有函数可以返回 typedef _list_iterator<T, Ref, Ptr> self;//这里要传 Ref 和 Ptr 不然const版本没有函数可以返回 Node* _node;//接收节点 _list_iterator(Node* node) :_node(node) {} Ref operator*()//*重载 不需要传参数 { return _node->_val; } Ptr operator->() { //return &(operaotr*()); return &_node->_val; } self& operator++()//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { _node = _node->next; return *this; } self operator++(int)//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { self tmp(*this); _node = _node->next; return tmp; } self& operator--()//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { _node = _node->prve; return _node; } self operator--(int)//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { self tmp(*this); _node = _node->prve; return tmp; } bool operator!=(const self& it)//传过来的是迭代器类型 { return _node != it._node; } bool operator==(const self& it) { return _node == it.node; } };
list本体
//双向迭代器 //head是哨兵位 头是哨兵位的下一个 位是哨兵位的上一个 //接受是哨兵位 //cbegin和cend 是自创 非官方 const_iterator cbegin() const { return const_iterator(head->next);//返回的是迭代器 所以要创建迭代器再返回 } const_iterator cend() const { return const_iterator(head);//返回的是迭代器 所以要创建迭代器再返回 } const_iterator begin() const { return const_iterator(head->next);//返回的是迭代器 所以要创建迭代器再返回 } const_iterator end() const { return const_iterator(head);//返回的是迭代器 所以要创建迭代器再返回 } iterator begin() { return iterator(head->next);//返回的是迭代器 所以要创建迭代器再返回 } iterator end() { return iterator(head);//返回的是迭代器 所以要创建迭代器再返回 }
list() { head = new node(); head->next = head; head->prve = head; }
template<class K> list(K cur, K end) { empty_into(); while (cur != end) { push_back(*cur); ++cur; } }
void empty_into() { head = new node(); head->next = head; head->prve = head; }
void swap(list<T>& lv)//交换数据时 不允许加const!!! { std::swap(head, lv.head); }
////传统写法 //list(const list<T>& lv) //{ // empty_into();//初始化 // for (auto e : lv) // { // push_back(e); // } //}
//现代写法 list(const list<T>& lv) { empty_into();//初始化 list<T> tmp(lv.begin(), lv.end()); swap(tmp); }
list<T>& operator=(list<T> lv) { swap(lv); return *this; }
insert
在某个位置插入某个值
因为这是节点,不存在下标,所以是传迭代器
但这个insert是不存在迭代器失效的问题的
首先创建一个新节点,用来存储要传进来的数据
然后我们用一个新节点记录来存储这个迭代器的位置。
然后用这个节点找到它的前一个节点
接下来就是链接
这个函数为什么不会存在迭代器失效?
因为这个函数是用指针链接,其次他们是没有直接改变pos,pos只是给他们提供位置,内部数据时不会对pos改动的,所以pos不会失效,其次list的结构问题,要插入节点,是创建这个节点的新空间,也就是新地址,不想vector的扩容,是整个顺序表都搬到另一个新空间,所以pos是不存在失效的。本质就是pos并未改动
void insert(iterator pos, const T& val) { node* newcapacity = new node(val); node* cur = pos._node; node* prve = cur->prve; //prve newcapacity pos prve->next = newcapacity; newcapacity->prve = prve; newcapacity->next = cur; cur->prve = newcapacity; }
erase
它要删除某个位置,list的结构是链表,所以传的也是迭代器,不存在下标。
但pos不能删除end (end就是head哨兵位)
用一个节点接收这个迭代器的位置,然后利用这个号节点找到它的前后,链接
最后删除这个节点 这时候,这节点是被删除的,也就是pos指向的节点,被删除了,那么pos就指向的个随机值,那你下次++时,指向随机值的迭代器的它++,你能确定它++到哪吗??所以这个迭代器就是失效了,而刚才我们已经有两个节点存储了刚才节点的前后的节点,那么我们的迭代器就更新为删除节点的下一个节点的位置即可,也就是erase删除后,自动++了。
就是返回的是迭代器,因为要对外面的迭代器更新,所以返回值是迭代器类型,但我们存储的是节点啊,所以这个节点要传到迭代器内初始化为迭代器类型,才能返回。
iterator erase(iterator pos)//返回的是迭代器 用于更新迭代器 { assert(pos != end()); node* poos = pos._node; node* prve = poos->prve; node* cur = poos->next; prve->next = cur; cur->prve = prve; delete poos; return iterator(cur); }
push_back
实际就是插入到最后的位置,就可以直接复用insert。最后的位置就是head的上一个位置就是最后的位置
void pop_back() { erase(head->prve); }
push_front
在最开始的位置插入,迭代器就是begin的位置 复用insert即可
void push_front(const T& val)
{
insert(begin(), val);
}
pop_back
在最后的位置删除,复用erase即可
void pop_back() { erase(head->prve); }
pop_front
在最前的位置删除,复用erase即可
void pop_front() { erase(begin()); }
//置空 void clear() { iterator it = begin(); while (it != end()) { it = erase(it); } }
//析构 ~list() { clear(); delete[] head; head = nullptr; }
源码
#pragma once #include<list> #include<iostream> #include<assert.h> using namespace std; namespace moxuan { template<class T> //创建 构造节点的类 struct _list_node { _list_node<T>* next; _list_node<T>* prve; T _val; _list_node(const T& val=T()) :next(nullptr) , prve(nullptr) ,_val(val) { } }; template<class T , class Ref , class Ptr>//Ref Ptr 是可以很好的区分const与非const版本 //通过重命名 通过不同的命名 传过来的参数是不同的 struct _list_iterator { typedef _list_node<T> Node; //typedef _list_iterator<T, T&, T*> self;//这里要传 Ref 和 Ptr 不然const版本没有函数可以返回 typedef _list_iterator<T, Ref, Ptr> self;//这里要传 Ref 和 Ptr 不然const版本没有函数可以返回 Node* _node;//接收节点 _list_iterator(Node* node) :_node(node) {} Ref operator*()//*重载 不需要传参数 { return _node->_val; } Ptr operator->() { //return &(operaotr*()); return &_node->_val; } self& operator++()//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { _node = _node->next; return *this; } self operator++(int)//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { self tmp(*this); _node = _node->next; return tmp; } self& operator--()//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { _node = _node->prve; return _node; } self operator--(int)//++后 返回的是迭代器类型 因为node是*类型 所以_list_iterator不能加引用 { self tmp(*this); _node = _node->prve; return tmp; } bool operator!=(const self& it)//传过来的是迭代器类型 { return _node != it._node; } bool operator==(const self& it) { return _node == it.node; } }; template<class T> class list { public: typedef _list_node<T> node; typedef _list_iterator<T, T&, T*> iterator; typedef _list_iterator<T, const T&, const T*> const_iterator;//根据名字不同 传过去的const和非const不同 //两个版本的T 都不允许加const 因为 构造时 是T 而传给迭代器时 是const T 是不同的,无法相互交融,报错 //通过重命名 通过不同的命名 传过来的参数是不同的 //双向迭代器 //head是哨兵位 头是哨兵位的下一个 位是哨兵位的上一个 //接受是哨兵位 //cbegin和cend 是自创 非官方 const_iterator cbegin() const { return const_iterator(head->next);//返回的是迭代器 所以要创建迭代器再返回 } const_iterator cend() const { return const_iterator(head);//返回的是迭代器 所以要创建迭代器再返回 } const_iterator begin() const { return const_iterator(head->next);//返回的是迭代器 所以要创建迭代器再返回 } const_iterator end() const { return const_iterator(head);//返回的是迭代器 所以要创建迭代器再返回 } iterator begin() { return iterator(head->next);//返回的是迭代器 所以要创建迭代器再返回 } iterator end() { return iterator(head);//返回的是迭代器 所以要创建迭代器再返回 } list() { head = new node(); head->next = head; head->prve = head; } void insert(iterator pos, const T& val) { node* newcapacity = new node(val); node* cur = pos._node; node* prve = cur->prve; //prve newcapacity pos prve->next = newcapacity; newcapacity->prve = prve; newcapacity->next = cur; cur->prve = newcapacity; } iterator erase(iterator pos)//返回的是迭代器 用于更新迭代器 { assert(pos != end()); node* poos = pos._node; node* prve = poos->prve; node* cur = poos->next; prve->next = cur; cur->prve = prve; delete poos; return iterator(cur); } //找到尾节点 //创建新节点 //链接 void push_back(const T& val) { ////找节点和创建节点 //node* tail = head->prve; //node* newnode = new node(val); ////链接 //tail->next = newnode; //newnode->prve = tail; //newnode->next = head; //head->prve = newnode; insert(end()--, val); } void push_front(const T& val) { insert(begin(), val); } void pop_back() { erase(head->prve); } void pop_front() { erase(begin()); } //置空 void clear() { iterator it = begin(); while (it != end()) { it = erase(it); } } //析构 ~list() { clear(); delete[] head; head = nullptr; } void empty_into() { head = new node(); head->next = head; head->prve = head; } template<class K> list(K cur, K end) { empty_into(); while (cur != end) { push_back(*cur); ++cur; } } void swap(list<T>& lv)//交换数据时 不允许加const!!! { std::swap(head, lv.head); } ////传统写法 //list(const list<T>& lv) //{ // empty_into();//初始化 // for (auto e : lv) // { // push_back(e); // } //} //现代写法 list(const list<T>& lv) { empty_into();//初始化 list<T> tmp(lv.begin(), lv.end()); swap(tmp); } list<T>& operator=(list<T> lv) { swap(lv); return *this; } private: node* head;//创建头节点 };
测试代码
void test1() { list<int> lv; lv.push_back(1); lv.push_back(2); lv.push_back(3); lv.push_back(4); lv.push_back(5); lv.push_back(6); list<int>::iterator it = lv.begin(); while (it != lv.end()) { cout << *it << " "; ++it; } } struct AA { AA(int a=0, int b=0) // 传的是结构体 类型必须有缺省值 :a(a) , b(b) { } int a; int b; }; void print_list(const list<int>& lv) { list<int>::const_iterator it2 = lv.begin(); while (it2 != lv.end()) { //*it2 = 10; cout << *it2 << " "; ++it2; } cout << endl; } void test2() { list<AA> lb; //传的是结构体 类型必须有缺省值 lb.push_back(AA(1, 1)); lb.push_back(AA(2, 2)); lb.push_back(AA(3, 3)); lb.push_back(AA(4, 4)); list<AA>::iterator it1 = lb.begin(); while (it1 != lb.end()) { cout << it1->a << " " << it1->b << endl; ++it1; } list<int> lv; lv.push_back(1); lv.push_back(2); lv.push_back(3); lv.push_back(4); //想调用const版本 需要对这个lv成员传参 定义成const 才能调用得到 不然begin是默认为非const版本 //也可以直接写cbegin cend 让他不用传参 也可以直接调用const版本 (自创 非官方) list<int>::const_iterator it2 = lv.cbegin(); while (it2 != lv.cend()) { //*it2 = 10; cout << *it2 << " "; ++it2; } cout << endl; print_list(lv); } void test3() { list<int> ls; ls.push_back(1); ls.push_back(2); ls.push_back(3); ls.push_back(4); list<int>::iterator it = ls.begin(); //while (it != ls.end()) //{ // if (*it % 2 == 0) // { // ls.insert(it, 100); // } // ++it; //} //for (auto e : ls) //{ // cout << e << " "; //} //cout << endl; //list<int>::iterator it1 = ls.begin(); //while (it1 != ls.end()) //{ // if (*it1 % 2 == 0) // { // it1=ls.erase(it1);//erase会造成迭代器失效 所以需要更新迭代器 并且迭代器返回的是pos的下一个位置,所以不用++ // } // else // { // ++it1; // } //} ls.push_front(1); ls.push_front(2); ls.push_front(3); ls.push_front(4); ls.pop_back(); ls.pop_back(); ls.pop_front(); ls.pop_front(); for (auto e : ls) { cout << e << " "; } } void test4() { list<int> lt; lt.push_back(1); lt.push_back(2); lt.push_back(3); lt.push_back(4); list<int> iv(lt); list<int> io(iv.begin(), iv.end()); list<int> ip = iv; for (auto e : lt) { cout << e << " "; } cout << endl; for (auto e : io) { cout << e << " "; } cout << endl; for (auto e : iv) { cout << e << " "; } cout << endl; for (auto e : ip) { cout << e << " "; } cout << endl; }

浙公网安备 33010602011771号