C++ list的常用接口
这里写目录标题
- <font color="#FF00FF">1. list类对象的常见构造
- <font color="#FF00FF">list capacity
- <font color="#FF00FF">list iterator的使用
- <font color="#FF00FF">list element access
- <font color="#FF00FF">list modifiers
- <font color="#FF00FF">list的迭代器失效
- <font color="#FF00FF">模拟实现list
- <font color="#FF00FF">list与vector的对比
1. list类对象的常见构造
这里和vector极其相似,就简单写了
list capacity
list iterator的使用
list element access
list modifiers
list的迭代器失效
迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
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); //在删除数据时,这里和vector或者string一样都是这么改,}
}
模拟实现list
list的底层结构为带头结点的双向循环链表,所以list空间并不连续,所以它 *it 取不到数据(因为it可以理解是指向结点的指针,那·*it就是结点了,而不是我们想要的数据),并且它也不能++和- -,所以我们对迭代器进行封装。
list.h
#pragma once
#include<iostream>
using namespace std;
namespace bit
{template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x = T()):_data(x), _prev(nullptr), _next(nullptr){}};// typedef list_iterator<T, T&, T*> iterator;// typedef list_iterator<T, const T&, const T*> const_iterator;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){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_iterator<T, const T&, const T*> const_iterator;iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const iterator begin()const{return iterator(_head->_next);}const iterator end()const{return iterator(_head);}void empty_init(){_head = new Node();_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}// lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}//lt2=lt1list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void swap(list<T>& tmp){swap(_head, tmp._head);swap(_size, tmp._size);}void clear(){auto it = begin();while (it != end()){it=erase(it);}}list(size_t n, const T& val = T()){empty_init();for (size_t i = 0; i < n; i++){push_back(val);}}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}void pop_back(){erase(--end());}iterator insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;return iterator(newnode);}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;_size--;return iterator(next);}template<class T>void swap(T& a, T& b){T c(a); a = b; b = c;}template<class T>void swap(list<I>& a, list<T>& b){a.swap(b);}private:Node* _head;size_t _size;};
}
list与vector的对比
vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不同,其主要不同如下: