《C++ list 完全指南:list的模拟实现》
《C++ list 完全指南:list的模拟实现》
文章目录
- 《C++ list 完全指南:list的模拟实现》
- 一、定义 list 的成员变量
- 二、list 的接口实现
-
- (1)list的迭代器实现
- (2)list的默认成员函数
-
- 2.1 list的构造函数
- 2.2 list的析构函数
- 2.3 list的赋值重载
- 2.4 list的拷贝构造
- (3)list的容量操作实现
- (4)list的访问操作实现
- (5)list的插入和删除
- (6)list的修改操作
- 三、list 源代码总结
-
- List.h
- Test.cpp
- NewTest.cpp
一、定义 list 的成员变量
list底层就是双向循环链表!
二、list 的接口实现
(1)list的迭代器实现
左边是前置++前置- -,右边是后置++后置- -
list 中对不同迭代器类型进行typedef简化
接下来是list的反向迭代器
代码如下(示例):
template<class Iterator> class ReverseListIterator{// 注意:此处typename的作用是明确告诉编译器,Ref是Iterator类中的类型,而不是静态//成员变量// 否则编译器编译时就不知道Ref是Iterator中的类型还是静态成员变量// 因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;public:// 构造ReverseListIterator(Iterator it): _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;};
(2)list的默认成员函数
2.1 list的构造函数
这四种构造函数方式可能会用到empty_init函数
第一种情况:构造的list中包含n个值为val的元素(这里会使用resize)
第二种情况:构造空的list
第三种情况:拷贝构造函数
第四种情况:用(first , last)区间中的元素构造list
2.2 list的析构函数
2.3 list的赋值重载
2.4 list的拷贝构造
(3)list的容量操作实现
size( )直接返回有效元素的个数
empty( )判断有效元素个数是否为0
clear( )要清理掉除了头结点以外的所有节点,我们直接用erase删除即可
resize和string、vector实现大差不差,这里直接上图
(4)list的访问操作实现
list列表并不支持重载operator[ ],我们只能实现front( )和back( )
(5)list的插入和删除
在实现insert( )和erase( )两个函数时,要防止迭代器失效
insert( )插入并没有使迭代器失效,为了防止,迭代器应指向新插入的节点
erase( )为了防止迭代器失效,需要返回删除元素的下一个元素的迭代器
(6)list的修改操作
如果用老方法的话就会显得很复杂,还需要重新插入节点,进行前后的链接!
push_back( )和pop_back( )都可以复用 insert( ) 和 earse( )
swap( )函数没什么说的,就是将_head 和 _size 进行交换
三、list 源代码总结
List.h
代码如下(示例):
#pragma once#includenamespace bit{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data), _next(nullptr), _prev(nullptr){}};template<class T, class Ref, class Ptr>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node;list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}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) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};/*templatestruct list_const_iterator{typedef list_node Node;typedef list_const_iterator Self;Node* _node;list_const_iterator(Node* node):_node(node){}const T& operator*(){return _node->_data;}const T* operator->(){return &_node->_data;}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) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};*/template<class T>class list{typedef list_node<T> Node;public:/*typedef list_iterator iterator;typedef list_const_iterator const_iterator;*/typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;iterator begin(){/*iterator it(_head->_next);return it;*///return iterator(_head->_next);return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}template<class Iterator> class ReverseListIterator{// 注意:此处typename的作用是明确告诉编译器,Ref是Iterator类中的类型,而不是静态//成员变量// 否则编译器编译时就不知道Ref是Iterator中的类型还是静态成员变量// 因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;public:// 构造ReverseListIterator(Iterator it): _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;};void resize(size_t n, const T& val = T()){if (n < _size){while (_size != n){pop_back();//尾删}}else{while (_size != n){push_back(val);//尾插}}}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}template<class Iterator>list(Iterator first, Iterator last){empty_initialize();while (first != last){push_back(*first);++first;}}list(size_t n, const T& val = T()){empty_initialize();resize(n, val);}list(int n, const T& val = T()){empty_initialize();resize(n, val);}list(const list<T>& lt){empty_initialize();list tmp(lt.begin(), lt.end());swap(tmp);//交换}list(initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}// lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}// lt1 = lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}// 16:18继续void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//void push_back(const T& x)//{//Node* newnode = new Node(x);//Node* tail = _head->_prev;//tail->_next = newnode;//newnode->_prev = tail;//newnode->_next = _head;//_head->_prev = newnode;//++_size;//}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);// prev newnode curnewnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;++_size;return newnode;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator erase(iterator pos){assert(pos != end());Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;--_size;return next;}// 可读可写T& front(){return *(begin());}T& back(){return *(--end());}// 可读不可写const T& front()const{return *(begin());}const T& back()const{return *(--end());}size_t size() const{return _size;}bool empty() const{return _size == 0;}private:Node* _head;size_t _size;};struct AA{int _a1 = 1;int _a2 = 1;};// 按需实例化// T* const ptr1// const T* ptr2template<class Container>void print_container(const Container& con){// const iterator -> 迭代器本身不能修改// const_iterator -> 指向内容不能修改typename Container::const_iterator it = con.begin();//auto it = con.begin();while (it != con.end()){//*it += 10;cout << *it << \" \";++it;}cout << endl;for (auto e : con){cout << e << \" \";}cout << endl;}void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){*it += 10;cout << *it << \" \";++it;}cout << endl;for (auto e : lt){cout << e << \" \";}cout << endl;print_container(lt);list<AA> lta;lta.push_back(AA());lta.push_back(AA());lta.push_back(AA());lta.push_back(AA());list<AA>::iterator ita = lta.begin();while (ita != lta.end()){//cout << (*ita)._a1 << \":\" << (*ita)._a2 << endl;// 特殊处理,本来应该是两个->才合理,为了可读性,省略了一个->cout << ita->_a1 << \":\" << ita->_a2 << endl;cout << ita.operator->()->_a1 << \":\" << ita.operator->()->_a2 << endl;++ita;}cout << endl;}void test_list2(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);// insert以后迭代器不失效list<int>::iterator it = lt.begin();lt.insert(it, 10);*it += 100;print_container(lt);// erase以后迭代器失效// 删除所有的偶数it = lt.begin();while (it != lt.end()){if (*it % 2 == 0){it = lt.erase(it);}else{++it;}}print_container(lt);}void test_list3(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int> lt2(lt1);print_container(lt1);print_container(lt2);list<int> lt3;lt3.push_back(10);lt3.push_back(20);lt3.push_back(30);lt3.push_back(40);lt1 = lt3;print_container(lt1);print_container(lt3);}void func(const list<int>& lt){print_container(lt);}void test_list4(){// 直接构造list<int> lt0({ 1,2,3,4,5,6 });// 隐式类型转换list<int> lt1 = { 1,2,3,4,5,6,7,8 };const list<int>& lt3 = { 1,2,3,4,5,6,7,8 };func(lt0);func({ 1,2,3,4,5,6 });print_container(lt1);//auto il = { 10, 20, 30 };/*initializer_list il = { 10, 20, 30 };cout << typeid(il).name() << endl;cout << sizeof(il) << endl;*/}}
Test.cpp
代码如下(示例):
#include#include#include#includeusing namespace std;void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << \" \";++it;}cout << endl;for (auto e : lt){cout << e << \" \";}cout << endl;/*it = lt.begin();lt.erase(it + 3);*/// 不支持,要求随机迭代器//sort(lt.begin(), lt.end());string s(\"dadawdfadsa\");cout << s << endl;sort(s.begin(), s.end());cout << s << endl;}struct A{public:A(int a1 = 1, int a2 = 1):_a1(a1), _a2(a2){cout << \"A(int a1 = 1, int a2 = 1)\" << endl;}A(const A& aa):_a1(aa._a1), _a2(aa._a2){cout << \"A(const A& aa)\" << endl;}int _a1;int _a2;};void test_list2(){/*list lt;lt.push_back(1);lt.emplace_back(2);lt.emplace_back(3);lt.emplace_back(4);for (auto e : lt){cout << e << \" \";}cout << endl;*/list<A> lt;A aa1(1, 1);lt.push_back(aa1);lt.push_back(A(2, 2));//lt.push_back(3, 3);lt.emplace_back(aa1);lt.emplace_back(A(2, 2));cout << endl;// 支持直接传构造A对象的参数emplace_backlt.emplace_back(3, 3);}void test_list3(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);for (auto e : lt){cout << e << \" \";}cout << endl;auto it = lt.begin();int k = 3;while (k--){++it;}lt.insert(it, 30);for (auto e : lt){cout << e << \" \";}cout << endl;int x = 0;cin >> x;it = find(lt.begin(), lt.end(), x);if (it != lt.end()){lt.erase(it);}for (auto e : lt){cout << e << \" \";}cout << endl;}void test_list4(){list<int> lt;lt.push_back(1);lt.push_back(20);lt.push_back(3);lt.push_back(5);lt.push_back(4);lt.push_back(5);lt.push_back(6);for (auto e : lt){cout << e << \" \";}cout << endl;// 升序// lt.sort();// 降序 - 仿函数// less ls;// greater gt;// lt.sort(gt);lt.sort(greater<int>());// lt.reverse();//reverse(lt.begin(), lt.end());for (auto e : lt){cout << e << \" \";}cout << endl;std::list<double> first, second;first.push_back(3.1);first.push_back(2.2);first.push_back(2.9);second.push_back(3.7);second.push_back(7.1);second.push_back(1.4);first.sort();second.sort();first.merge(second);}void test_list5(){list<int> lt;lt.push_back(1);lt.push_back(20);lt.push_back(3);lt.push_back(5);lt.push_back(5);lt.push_back(4);lt.push_back(5);lt.push_back(6);lt.sort();for (auto e : lt){cout << e << \" \";}cout << endl;lt.unique();for (auto e : lt){cout << e << \" \";}cout << endl;}void test_list6(){// 一个链表节点转移给另一个链表std::list<int> mylist1, mylist2;std::list<int>::iterator it;// set some initial values:for (int i = 1; i <= 4; ++i)mylist1.push_back(i); // mylist1: 1 2 3 4for (int i = 1; i <= 3; ++i)mylist2.push_back(i * 10); // mylist2: 10 20 30it = mylist1.begin();++it; // points to 2mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4 // mylist2 (empty) // \"it\" still points to 2 (the 5th element// 调整当前链表节点的顺序list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);for (auto e : lt){cout << e << \" \";}cout << endl;int x = 0;cin >> x;it = find(lt.begin(), lt.end(), x);if (it != lt.end()){//lt.splice(lt.begin(), lt, it);lt.splice(lt.begin(), lt, it, lt.end());}for (auto e : lt){cout << e << \" \";}cout << endl;}void test_op1(){srand((unsigned int)time(0));const int N = 1000000;list<int> lt1;vector<int> v;for (int i = 0; i < N; ++i){auto e = rand() + i;lt1.push_back(e);v.push_back(e);}int begin1 = clock();// 排序sort(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf(\"vector sort:%d\\n\", end1 - begin1);printf(\"list sort:%d\\n\", end2 - begin2);}void test_op2(){srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){auto e = rand() + i;lt1.push_back(e);lt2.push_back(e);}int begin1 = clock();// 拷贝vectorvector<int> v(lt2.begin(), lt2.end());// 排序sort(v.begin(), v.end());// 拷贝回lt2lt2.assign(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf(\"list copy vector sort copy list sort:%d\\n\", end1 - begin1);printf(\"list sort:%d\\n\", end2 - begin2);}#include\"List.h\"// 10:35int main(){//test_list6();//test_op2();bit::test_list4();return 0;}
NewTest.cpp
代码如下(示例):
//#include //using namespace std;//#include //int main()//{// forward_list fl = { 1, 2, 3 };// // 在头部插入元素// fl.push_front(0);//// // 遍历并输出// for (int num : fl)// {// cout << num << \" \";// }// cout << endl;//// return 0;//}#include #include using namespace std;//int main()//{// list myList = { 10, 20, 30, 40, 50 };// // 在头部插入元素// myList.push_front(5);// // 在尾部插入元素// myList.push_back(60);// // 遍历并输出// for (int num : myList) {// cout << num << \" \";// }// cout << endl;//// // 删除指定元素// myList.remove(30);//// // 再次遍历输出// for (int num : myList) {// cout << num << \" \";// }// cout << endl;// return 0;//}void Test1(){ // 默认构造函数 list<int> numbers1; cout << \"默认构造: \"; for (const auto& num : numbers1) { cout << num << \" \"; } cout << endl; // n个val构造 list<int> numbers2(5, 10); cout << \"n个val构造: \"; for (const auto& num : numbers2) { cout << num << \" \"; } cout << endl; int arr[] = { 1, 2, 3 }; // 通过vector的迭代器初始化 list<int> numbers3(arr, arr + sizeof(arr) / sizeof(arr[0])); cout << \"迭代器区间构造: \"; for (const auto& num : numbers3) { cout << num << \" \"; } cout << endl; list<int> numbers4 = { 4, 5, 6 }; // 拷贝构造 list<int> numbers5(numbers4); cout << \"拷贝构造: \"; for (const auto& num : numbers5) { cout << num << \" \"; } cout << endl; numbers1 = numbers2; // 赋值重载 cout << \"赋值重载: \"; for (const auto& num : numbers1) { cout << num << \" \"; } cout << endl;}void Test2(){ list<int> numbers = { 1, 2, 3, 4, 5 }; list<int>::iterator it = numbers.begin(); cout << \"First element: \" << *it << endl; while (it != numbers.end()) { cout << *it << \" \"; ++it; } // 注意:这里不能直接解引用it,因为此时它指向的是头节点 cout << endl;}void Test3(){ list<int> numbers = { 1, 2, 3, 4, 5 }; list<int>::reverse_iterator rit = numbers.rbegin(); cout << \"Last element: \" << *rit << endl; while (rit != numbers.rend()) { cout << *rit << \" \"; ++rit; } cout << endl;}void Test4(){ list<int> numbers = { 1, 2, 3, 4, 5 }; cout << \"Size of list: \" << numbers.size() << endl; cout << \"Max size of list: \" << numbers.max_size() << endl;}void Test5(){ list<int> numbers; if (numbers.empty()) { cout << \"List is empty\" << endl; } numbers = { 1, 2, 3 }; numbers.clear(); if (numbers.empty()) { cout << \"List is cleared and now empty\" << endl; }}void Test6(){ list<int> numbers = { 1, 2, 3 }; numbers.resize(5); cout << \"After resizing to 5: \"; for (auto& num : numbers) { cout << num << \" \"; } cout << endl; numbers.resize(2); cout << \"After resizing to 2: \"; for (auto& num : numbers) { cout << num << \" \"; } cout << endl;}void Test7(){ list<int> myList = { 10, 20, 30 }; // 创建一个包含元素的列表 // 输出列表的第一个元素 cout << \"The front element is: \" << myList.front() << endl; // 输出列表的最后一个元素 cout << \"The back element is: \" << myList.back() << endl;}void Test8(){ list<int> myList; // 创建一个空列表 myList.push_back(10); // 在列表尾部添加元素 10 myList.push_back(20); // 在列表尾部添加元素 20 cout << \"列表元素: \"; for (auto& num : myList) { cout << num << \" \"; } cout << endl; myList.pop_back(); // 删除列表尾部的元素 cout << \"删除尾部元素后列表元素: \"; for (auto& num : myList) { cout << num << \" \"; } cout << endl;}void Test9(){ list<int> myList; // 创建一个空列表 myList.push_front(5); // 在列表头部添加元素 5 myList.push_front(3); // 在列表头部添加元素 3 cout << \"列表元素: \"; for (auto& num : myList) { cout << num << \" \"; } cout << endl; myList.pop_front(); // 删除列表头部的元素 cout << \"删除头部元素后列表元素: \"; for (auto& num : myList) { cout << num << \" \"; } cout << endl;}void Test10(){ list<int> myList = { 1, 2, 3 }; list<int>::iterator it = myList.begin(); it = myList.insert(it, 4); // 这里迭代器 it 失效 it = myList.insert(it, 5); // 这里迭代器 it 失效 for (auto& num : myList) { cout << num << \" \"; } cout << endl;}void Test11(){ list<int> myList = { 1, 2, 3, 4, 5 }; list<int>::iterator it = myList.begin(); it = myList.erase(it); // 迭代器 it 失效 it = myList.erase(it); // 迭代器 it 失效 for (auto& num : myList) { cout << num << \" \"; } cout << endl;}void Test12(){ list<int> list1 = { 1, 2, 3 }; list<int> list2 = { 4, 5, 6 }; cout << \"交换之前:\" << endl; for (auto& num : list1) { cout << num << \" \"; } cout << endl; for (auto& num : list2) { cout << num << \" \"; } cout << endl; list1.swap(list2); cout << \"交换之前:\" << endl; for (auto& num : list1) { cout << num << \" \"; } cout << endl; for (auto& num : list2) { cout << num << \" \"; } cout << endl;}void Test13(){ list<int> list1 = { 1, 2, 3 }; list<int> list2 = { 4, 5 }; // 将 list2 的元素转移到 list1 中 list1.splice(list1.end(), list2); for (auto num : list1) { cout << num << \" \"; } cout << endl;}void Test14(){ list<int> myList = { 1, 2, 2, 3, 2 }; // 移除值为 2 的元素 myList.remove(2); for (auto num : myList) { cout << num << \" \"; } cout << endl;}bool isEven(int num) { return num % 2 == 0;}void Test15() { list<int> myList = { 1, 2, 3, 4, 5, 6 }; // 移除满足偶数条件的元素 myList.remove_if(isEven); for (auto num : myList) { cout << num << \" \"; } cout << endl;}void Test16(){ list<int> myList = { 1, 2, 2, 3, 3, 3 }; // 移除相邻的重复元素 myList.unique(); for (auto num : myList) { cout << num << \" \"; } cout << endl;}void Test17(){ list<int> list1 = { 1, 3, 5 }; list<int> list2 = { 2, 4, 6 }; list1.sort(); list2.sort(); // 合并两个已排序的列表 list1.merge(list2); for (auto num : list1) { cout << num << \" \"; } cout << endl;}void Test18() { list<int> myList = { 3, 1, 4, 1, 5, 9, 2, 6, 5 }; // 对列表进行排序 myList.sort(); for (auto num : myList) { cout << num << \" \"; } cout << endl;}void Test19(){ list<int> l2 = { 1,2,4,5 }; l2.reverse();//list中的reverse reverse(l2.begin(), l2.end());//算法库中的reverse for (auto& num : l2) { cout << num << \" \"; }}void TestListIterator1(){ int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; list<int> l(array, array + sizeof(array) / sizeof(array[0])); auto it = l.begin(); while (it != l.end()) { // erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给 //其赋值 l.erase(it); ++it; }}// 改正void TestListIterator(){ int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; list<int> l(array, array + sizeof(array) / sizeof(array[0])); auto it = l.begin(); while (it != l.end()) { l.erase(it++); // it = l.erase(it); }}int main(){ //Test1(); //Test2(); //Test4(); //Test5(); //Test6(); //Test7(); //Test8(); //Test9(); //Test10(); //Test11(); //Test12(); //Test13(); //Test14(); //Test15(); //Test16(); //Test17(); //Test18(); Test19();}