c++-list
C++-list
std::list
是C++标准模板库(STL)提供的双向链表容器,它提供了高效的插入和删除操作,特别适合频繁修改的序列。定义在 <list>
头文件中,属于 std
命名空间。该类的接口与常规容器接口基本一致。
模板原型:
template < class T, class Alloc = allocator<T> > class list;
allocator<T>:STL空间配置器(内存池)。
基本特性:
-
实现方式:双向链表结构,每个元素包含指向前驱和后继的指针。
-
内存分配:元素在内存中非连续存储的,通过指针链接。
-
泛型容器:通过模板实现,可以存储任何类型的元素。
-
迭代器:双向迭代器(支持++和–操作)。
1. 底层理解
list 底层是 带头双向循环链表。
template<typename T>
struct list_node{T val;list_node* prev;list_node* next;list_node(const T& data = T()) :val(data) , prev(nullptr) , next(nullptr) {}
};
template<typename T>
class list {private:list_node<T>* node;
}
2. 成员函数
2.1 成员类型
成员类型 | 解释 |
---|---|
value_type | 第一个模板参数(T) |
allocator_type | 第二个模板参数(Alloc) |
size_type | 无符号整数(size_t) |
reference | 类型引用(T&) |
const_reference | const类型引用(const T&) |
2.2 构造函数
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | explicit list (const allocator_type& alloc = allocator_type()) | 默认构造 |
2️⃣ | list (const list& x) | 拷贝构造 |
3️⃣ | explicit list (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()) | 使用 n 个 val 值初始化 |
4️⃣ | template <class InputIterator> list (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) | 使用一段迭代器区间初始化 |
2.3 赋值重载
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | list& operator= (const list& x) | 两个已存在的 list 对象的赋值 |
2.4 迭代器
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | iterator begin() | 返回指向 list 对象中第一个元素的迭代器 |
2️⃣ | const_iterator begin() const | 返回指向 list 对象中第一个元素的 const迭代器 |
3️⃣ | iterator end() | 返回指向 list 对象末尾元素之后位置的迭代器 |
4️⃣ | const_iterator end() const | 返回指向 list 对象末尾元素之后位置的 const迭代器 |
5️⃣ | reverse_iterator rbegin() | 返回指向 list 对象末尾元素的反向迭代器 |
6️⃣ | const_reverse_iterator rbegin() const | 返回指向 list 对象末尾元素的const反向迭代器 |
7️⃣ | reverse_iterator() rend() | 返回指向 list 对象起始元素之前位置的反向迭代器 |
8️⃣ | const_reverse_iterator() rend() const | 返回指向 list 对象起始元素之前位置的const反向迭代器 |
2.5 容量相关的接口
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | size_type size() const | 返回 list 对象中元素的数量 |
2️⃣ | bool empty() const | 判断当前 list 对象是否为空 |
2.6 元素的访问
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | reference front() | 返回 list 对象第一个元素的引用 |
2️⃣ | const_reference front() const | 返回 const list 对象第一个元素的 const引用 |
3️⃣ | reference back() | 返回 list 对象最后一个元素的引用 |
4️⃣ | const_reference back() const | 返回 const list 对象最后一个元素的引用 |
2.7 修改相关的接口
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | template <class InputIterator> void assign (InputIterator first, InputIterator last) | 使用一段迭代器区间赋值给 list 对象(通常使用其他容器) |
2️⃣ | void push_front (const value_type& val) | 在 list 对象头部插入 val 元素 |
3️⃣ | void pop_front() | 在 list 对象头部删除一个元素 |
4️⃣ | void push_back (const value_type& val) | 在 list 对象尾部插入 val 元素 |
5️⃣ | void pop_back() | 在 list 对象尾部删除一个元素 |
6️⃣ | iterator insert (iterator pos, const value_type& val); | 在 list 对象的 pos 位置迭代器插入 val 元素,返回新插入元素的迭代器 |
7️⃣ | iterator erase (iterator pos); | 删除 list 对象的 pos 位置迭代器元素,返回删除位置元素的下一个迭代器 |
8️⃣ | void clear(); | 清空 list 对象中所有元素 |
2.8 其他操作
序号 | 函数原型 | 说明 |
---|---|---|
1️⃣ | void reverse() | 逆置 list 对象中的元素 |
2️⃣ | void sort() | 排序 list 对象中的元素(默认升序) |
3️⃣ | void merge (list& x) | 合并两个有序的 list,将 x 对象中的所有元素合并到当前 list 中,合并完后 x 将变为空链表 |
4️⃣ | void unique() | 去重,但前提需要 list 对象有序 |
5️⃣ | void remove (const value_type& val) | 移除所有 val 元素 |
6️⃣ | void splice (iterator position, list& x) | 将x链表中的所有元素移动到当前链表的 position迭代器之前,移动后 x 变为空链表 |
7️⃣ | void splice (iterator position, list& x, iterator i) | 将x链表中 i 位置迭代器元素移动到当前链表的 position迭代器之前 |
8️⃣ | void splice (iterator position, list& x, iterator first, iterator last); | 将x链表一段迭代器区间移动到当前链表的 position迭代器之前 |
- reverse
- sort
- merge
- unique
- remove
6.splice
3. list迭代器失效
C++中,list 与 vector 迭代器失效有所不同,list迭代器失效主要发生在 元素被删除时
迭代器失效的情况:
-
erase 时被删除位置元素迭代器失效。
- 解决方式:通过 erase 返回值重新获取迭代器(erase返回删除元素的下一个位置迭代器)
-
整个 list 被销毁或赋值时,所有迭代器都会失效。
4. list模拟实现
// list.hpp
#pragma once#include <iostream>
#include <cassert>namespace simulate_list {template<typename T>struct list_node{T val;list_node* prev;list_node* next;list_node(const T& data = T()) :val(data) , prev(nullptr) , next(nullptr) {}};template<typename T , typename Ref , typename Ptr>struct __list_iterator {typedef list_node<T> node;typedef __list_iterator<T , Ref , Ptr> self;__list_iterator(node* nodeptr) :cur(nodeptr) {}self& operator++() {cur = cur->next;return *this;}self operator++(int) {self temp(cur);cur = cur->next;return temp;}self& operator--() {cur = cur->prev;return *this;}self operator--(int) {self temp(cur);cur = cur->prev;return temp;}Ref operator*() {return cur->val;}Ptr operator->() {return &(operator*());}bool operator==(const self& s) {return cur == s.cur;}bool operator!=(const self& s) {return cur != s.cur;}node* cur;};template<typename 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 const_iterator(head->next); }const_iterator end() const { return const_iterator(head); }bool empty() const { return head->next == head; }T& front() { assert(!empty()); return head->next->val; }T& back() { assert(!empty()); return head->prev->val; }const T& front() const { assert(!empty()); return head->next->val; }const T& back() const { assert(!empty()); return head->prev->val; }size_t size() const {size_t count = 0;for (auto& a : *this) count++;return count; }void clear() {auto it = begin();while (it != end())it = erase(it);}void initializer_list() {head = new node;head->prev = head;head->next = head;}list<T>() {initializer_list();}list<T>(const list<T>& l) {initializer_list();for (auto& node : l)push_back(node);}list<T>& operator=(list<T> l) {std::swap(head , l.head);return *this;}~list<T>() {clear();delete head;head = nullptr;}iterator insert(iterator position , const T& val);iterator erase(iterator position);void push_front(const T& val) { insert(begin() , val); }void pop_front() { assert(!empty()); erase(begin()); }void push_back(const T& val) { insert(end() , val); }void pop_back() { assert(!empty()); erase(--end()); } private:node* head = nullptr;}; template<typename T>typename list<T>::iterator list<T>::insert(list<T>::iterator position , const T& val) {node* prev = position.cur->prev;node* newnode = new node(val);prev->next = newnode;newnode->prev = prev;newnode->next = position.cur;position.cur->prev = newnode;return iterator(newnode); // 返回新插入节点的迭代器}template<typename T>typename list<T>::iterator list<T>::erase(list<T>::iterator position) {node* prev = position.cur->prev;node* next = position.cur->next;prev->next = next;next->prev = prev;delete position.cur;return iterator(next); // 返回删除元素的下一个元素}} // namespace simulate_list end