目录
3、将一个链表或链表的结点或链表的迭代器区间插入到另一个链表的某结点之前:splice()(还可以自己转移自己(LRU))
一、含义介绍
1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器(时间效率都是O(1)),并且该容器可以前后双向迭代。
2. list的底层是带头双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)
6、list不支持[ ]的使用,因为空间不连续。
7、头文件:<list>
8、支持头插头删,尾插尾删。
9、大部分接口都和vector一样,可以查看文档
二、遍历(迭代器和范围for)
因为不支持[ ],所以通常使用迭代器和for进行遍历;
int main() { 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 for (auto e : lt) { cout << e << " "; } cout << endl; }
三、部分接口介绍
1.将两个有序链表归并成一个:merge()
void test2() { list<int> v1, v2; v1.push_back(1); v1.push_back(2); v1.push_back(3); v2.push_back(4); v2.push_back(5); v2.push_back(6); v1.merge(v2); list<int>::iterator it = v1.begin(); while (it != v1.end()) { cout << *it << " "; ++it; } }
2、去重:unique()
该接口有一个前提,前提就是相同的数要挨在一起,所以通常都是先进行排序在使用此接口
void test3() { list<int> v1, v2; v1.push_back(1); v1.push_back(2); v1.push_back(2); v1.push_back(3); v1.push_back(3); v1.push_back(3); v1.push_back(4); v1.unique(); list<int>::iterator it = v1.begin(); while (it != v1.end()) { cout << *it << " "; ++it; } }
3、将一个链表或链表的结点或链表的迭代器区间插入到另一个链表的某结点之前:splice()(还可以自己转移自己(LRU))
将自己的2转移到末尾:
void test4() { list<int> v1; v1.push_back(1); v1.push_back(2); v1.push_back(3); v1.push_back(4); v1.push_back(5); v1.splice(v1.end(), v1, find(v1.begin(), v1.end(), 2)); list<int>::iterator it = v1.begin(); while (it != v1.end()) { cout << *it << " "; ++it; } }
四、模拟实现list
namespace HF { //结点类 template <class T> struct ListNode { ListNode<T>* next; ListNode<T>* prev; T date; ListNode(const T& x = T()) :next(nullptr) ,prev(nullptr) ,date(x) {} }; //迭代器(结点的指针) template <class T> struct __list_iterator { typedef ListNode<T> Node; typedef __list_iterator self; Node* _node; __list_iterator(Node* node) :_node(node) {} //重载前置++ self& operator++() { _node = _node->next; return *this; } //重载后置++ self& operator++(int) { self tmp(*this); _node = _node->next; return tmp; } //重载前置-- self& operator--() { _node = _node->prev; return *this; } //重载后置-- self& operator--(int) { self tmp(*this); _node = _node->prev; return tmp; } //重载* T& operator*() { return _node->date; } bool operator!=(const self& s) { return _node != s._node; } }; //链表类 template <class T> class list { typedef ListNode<T> Node; private: Node* _head; public: typedef __list_iterator<T> iterator; list() { empty_init(); } //拷贝构造 list( list<T>& lt) { empty_init(); for (const auto& e : lt) { push_back(e); } } //初始化 void empty_init() { _head = new Node; _head->next = _head; _head->prev = _head; } //析构 ~list() { clear(); delete _head; _head = nullptr; } iterator begin() { return _head->next; } iterator end() { return _head; } //尾插 void push_back(const T& x) { //没有insert时的写法 /*Node* newnode = new Node(x); Node* tail = _head->prev; tail->next = newnode; newnode->prev = tail; newnode->next = _head; _head->prev = newnode;*/ //复用insert insert(end(), x); } //头插 void push_front(const T& x) { insert(begin(), x); } //尾删 void pop_back() { erase(--end()); } //头删 void pop_front() { erase(begin()); } //在某个位置插入 iterator insert(iterator pos, const T& x) { Node* cur = pos._node; Node* prev = cur->prev; Node* newnode = new Node(x); prev->next = newnode; newnode->prev = prev; newnode->next = cur; cur->prev = newnode; //return iterator(newnode); //隐式类型转换 return newnode; } //删除指定结点 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); } } void swap(list<T>& lt) { std::swap(_head,lt._head); } //赋值重载 list<T>& opterator = (list<T> lt) { if (< != this) { swap(lt)* this; return *this; } } };