list的使用及模拟实现
list的使用
在本篇博客中介绍的list是带头双向循环链表
list的构造函数
构造包括:默认构造、赋值构造、迭代器构造、拷贝构造
Iterators:
- begin+end
返回迭代器的开始和末尾
- rbegin+rend
返回迭代器的末尾和开始
- cbegin+cend
返回const迭代器的开始与末尾
#include<iostream>
#include<list>using namespace std;void List_Test1()
{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;list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";rit++;}cout << endl;}int main()
{List_Test1();return 0;
}
Capacity:
- empty
判断list是否为空
- size
返回list的结点数量
#include<iostream>
#include<list>using namespace std;void List_Test2()
{list<int> lt;cout << lt.empty() << endl;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);cout << lt.empty() << endl;cout << lt.size() << endl;
}int main()
{List_Test2();return 0;
}
Element access:
- front
返回第一个元素
- back
返回最后一个元素
#include<iostream>
#include<list>using namespace std;void List_Test3()
{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);cout << lt.front() << endl;cout << lt.back() << endl;
}int main()
{List_Test3();return 0;
}
需要注意的是list容器不存在[]
,究竟是什么原因造成这样的结果:
迭代器的分类
按功能分
- iterator
- reverse_iterator
- const_iterator
- const_reverse_iterator
按性质分
-
单向迭代器:forward、unordered_map… 只能进行++
-
双向迭代器:list、map、set… 可以进行++和 - -
-
随机迭代器:vector、string、deque… 可以进行++、- -、+、-
随机迭代器包含了双向迭代器包含了单向迭代器,因此随机迭代器可以使用双向迭代器和单向迭代器的算法,而双向迭代器和单向迭代器不能使用随机迭代器的算法。由此可以回答上述问题,因为[]
只能在随机迭代器中使用,因此list没有[]
Modifiers:
- assign
给容器分配新的内容
- push_front
头插
- pop_front
头删
- push_back
尾插
- pop_back
尾删
- insert
选择位置插入数据
- erase
选择位置删除数据
- swap
交换数据
- resize
改变容器的大小
- clear
清除容器的内容
#include<iostream>
#include<list>using namespace std;void List_Test4()
{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);list<int> lt2;lt2.assign(lt.begin(), lt.end());list<int>::iterator it2 = lt2.begin();while (it2 != lt2.end()){cout << *it2 << " ";it2++;}cout << endl;lt.push_front(10);lt.push_back(20);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.pop_front();lt.pop_back();it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;it = lt.begin();int k = 3;while (k--){it++;}lt.insert(it, 30);lt.erase(it--);it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.swap(lt2);it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.resize(2);it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.clear();cout << lt.empty() << endl;
}int main()
{List_Test4();return 0;
}
Operations:
- splice
将一个链表剪切到另一个链表中
#include<iostream>
#include<list>using namespace std;void List_Test5()
{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);list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);lt.splice(lt.begin(), lt2);list<int>::iterator it2 = lt2.begin();while (it2 != lt2.end()){cout << *it2 << " ";it2++;}cout << endl;list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;
}int main()
{List_Test5();return 0;
}
- remove
删除指定数据
- remove_if
删除满足条件的所有数据
#include<iostream>
#include<list>using namespace std;bool signal_digit(const int& v)
{return (v < 10);
}void List_Test6()
{list<int> lt;lt.push_back(10);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.remove(4);it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.remove_if(signal_digit);it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;}int main()
{List_Test6();return 0;
}
- unique
删除重复的数,需要有序
- sort
将list进行排序(默认是升序)
#include<iostream>
#include<list>using namespace std;void List_Test7()
{list<int> lt;lt.push_back(10);lt.push_back(2);lt.push_back(4);lt.push_back(4);lt.push_back(1);lt.push_back(5);lt.sort();list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.unique();it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;//改成降序greater<int> gt;lt.sort(gt);it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;
}int main()
{List_Test7();return 0;
}
- merge
合并两个list链表
#include<iostream>
#include<list>using namespace std;void List_Test8()
{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);list<int> lt2;lt.push_back(10);lt.push_back(20);lt.push_back(30);lt.push_back(40);lt.push_back(50);lt.push_back(60);lt.merge(lt2);list<int>::iterator it = lt2.begin();while (it != lt2.end()){cout << *it << " ";it++;}cout << endl;it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;
}int main()
{List_Test8();return 0;
}
- reverse
反转链表
#include<iostream>
#include<list>using namespace std;void List_Test9()
{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);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;lt.reverse();it = lt.begin();while (it != lt.end()){cout << *it << " ";it++;}cout << endl;
}int main()
{List_Test9();return 0;
}
list的迭代器失效问题
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);auto it = lt.begin();while (it != lt.end()){lt.erase(it);it++;}return 0;
}
当运行这段代码时,程序会崩溃,这是因为erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给
其赋值
修改:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);auto it = lt.begin();while (it != lt.end()){lt.erase(it++);}return 0;
}
list的模拟实现
- list.h
实现list的构造函数,部分迭代器的功能,begin()、end()、insert()、push_back()、push_front()、erase()、pop_back()、pop_front()、size()、empty()
#pragma once
#include<assert.h>
#include<iostream>
using namespace std;namespace my_list
{template<class T>class list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data), _next(nullptr), _prev(nullptr){}};//struct是共有,class是私有template<class T, class Ref, class Ptr>struct list_iterator{typedef list_node<T> Node;//这一行代码的加入使得const和非const不需要繁琐的重新写冗余的代码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++(){Self tmp(*this);_node = _node->next;return tmp;}Self& operator--(){Self tmp(*this);_node = _node->prev;return tmp;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}};template<class T>class list{typedef list_node<T> Node;public:typedef list_iterator<T, T&, T*> iterator;typedef list_const_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;}void empty_list(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_list();}~list(){clear();delete _head;_head = nullptr;}list(const list<T>& lt){empty_list();for (auto& e : lt){push_back(e);}}//使得list<int> lt(1,2,3,4,5) 能够实现list(initializer_list<int> il){empty_list();for (auto& e : il){push_back(e);}}list<T>& operator=(list<T>& lt){swap(lt);return *this;}void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}void clear(){auto it = begin();while (it != end()){it = earse(it);}}void push_back(const T& x){//Node* newnode = new Node(x);//Node* tail = _head->_prev;//tail->_next = newnode;//newnode->_next = _head;//newnode->_prev = tail;//_head->_prev = newnode;//_size++;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){earse(end()--);}void pop_front(){earse(begin());}iterator earse(iterator it){assert(pos != end());Node* prev = it._node->_prev;Node* next = it._node->_next;prev->_next = next;next->_prev = prev;_size--;return next;}iterator insert(iterator it, const T& x){Node* newnode = new Node(x);Node* cur = it._node;Node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;_size++;return newnode;}private:Node* _head;size_t _size;};}