【C++容器】list使用全览

更多 C++语法知识在 C++语言学记专栏
往期 STL 容器看点:
这篇文章是关于 C++所有数据结构概览中的单独专题

顺序容器vectorarraylistdequeforward_list
关联容器set&multisetmap&multimap无序关联容器Unordered set&multisetUnordered map&multimap
容器适配器stackqueuepriority_queue其他容器string

首先,请确保包含了头文件:

#include <list>

std::list 是一个双向链表,它的主要优点是在序列的任何位置进行插入和删除操作都非常快(O(1)),但代价是失去了快速随机访问的能力。


1. 构造函数 (Constructors)

用于创建和初始化一个 list

  • list()

    • 功能:默认构造函数,创建一个空的 list

    • 示例std::list<int> l1;

  • list(size_type count, const T& value)

    • 功能:创建包含 count 个元素的 list,每个元素都被初始化为 value

    • 示例std::list<int> l2(5, 10); // 创建包含 5 个 int 的 list,每个都是 10

  • list(size_type count) (C++11 起)

    • 功能:创建包含 count 个元素的 list,并对每个元素进行值初始化。

    • 示例std::list<int> l3(5); // 创建包含 5 个 int 的 list,每个都是 0

  • list(InputIt first, InputIt last)

    • 功能:使用迭代器范围 [first, last) 内的元素来构造 list

    • 示例int arr[] = {1, 2, 3, 4, 5}; std::list<int> l4(arr, arr + 5);

  • list(const list& other)

    • 功能:拷贝构造函数,创建一个与 other 内容相同的 list

    • 示例std::list<int> l5(l4);

  • list(list&& other) (C++11)

    • 功能:移动构造函数,接管 other 的资源。

    • 示例std::list<int> l6(std::move(l5));

  • list(std::initializer_list<T> init) (C++11)

    • 功能:使用初始化列表来构造 list

    • 示例std::list<int> l7 = {1, 2, 3, 4, 5};


2. 迭代器 (Iterators)

用于遍历 list 中的元素。

  • begin() / cbegin()

    • 功能:返回指向 list 第一个元素的迭代器。
  • end() / cend()

    • 功能:返回指向 list 尾端(最后一个元素的下一个位置)的迭代器。
  • rbegin() / crbegin()

    • 功能:返回指向 list 最后一个元素的反向迭代器。
  • rend() / crend()

    • 功能:返回指向 list 第一个元素之前位置的反向迭代器。

重要提示list 的迭代器是双向迭代器 (Bidirectional Iterator),不是随机访问迭代器。这意味着你只能对它进行 ++-- 操作,不能进行 it + 5it > it2 这样的操作。

示例

std::list<int> l = {10, 20, 30};
// 正向遍历
for(auto it = l.begin(); it != l.end(); ++it) {
    std::cout << *it << " "; // 输出: 10 20 30
}
// 反向遍历
for(auto it = l.rbegin(); it != l.rend(); ++it) {
    std::cout << *it << " "; // 输出: 30 20 10
}

3. 大小 (Size)

管理 list 的大小。

  • size()

    • 功能:返回 list 中实际元素的数量。
  • empty()

    • 功能:检查 list 是否为空(即 size() == 0)。
  • max_size()

    • 功能:返回 list 理论上能容纳的最大元素数量。

重要提示list 没有 capacity()reserve() 方法。因为链表是基于节点的非连续存储,每个节点都是独立分配内存的,所以不存在预留空间的概念。


4. 元素访问 (Element Access)

获取 list 中的首尾元素。

  • front()

    • 功能:返回对第一个元素的引用。
  • back()

    • 功能:返回对最后一个元素的引用。

重要提示list 没有 operator[].at() 方法。因为它的非连续内存结构,无法在 O(1) 时间内进行随机访问。要访问中间元素,必须从头或尾开始遍历。

示例

std::list<int> l = {10, 20, 30, 40};
int first = l.front(); // first = 10
int last = l.back();   // last = 40

5. 修改器 (Modifiers)

改变 list 的内容,这是 list 的核心优势所在。

  • assign(): 功能同 vector

  • push_back(const T& value) / emplace_back(...)

    • 功能:在 list 的末尾添加一个元素。保证为 O(1)。
  • pop_back()

    • 功能:移除 list 的最后一个元素。O(1)。
  • push_front(const T& value) / emplace_front(...)

    • 功能:在 list头部添加一个元素。这是 list 的一个巨大优势。O(1)。
  • pop_front()

    • 功能:移除 list 的第一个元素。O(1)。
  • insert(const_iterator pos, ...)

    • 功能:在迭代器 pos 指向的位置之前插入元素。只要有迭代器,这个操作就是 O(1),远快于 vector 的 O(n)。
  • erase(const_iterator pos) / erase(const_iterator first, const_iterator last)

    • 功能:移除指定位置或范围的元素。同样,只要有迭代器,单个元素的删除就是 O(1)。
  • swap(list& other): 功能同 vector,O(1)。

  • clear(): 功能同 vector

  • resize(): 功能同 vector

示例

std::list<int> l = {10, 20, 30};
l.push_front(5);    // l: {5, 10, 20, 30}
l.push_back(35);    // l: {5, 10, 20, 30, 35}

auto it = l.begin();
std::advance(it, 2); // 移动迭代器到 20 的位置
l.insert(it, 15);   // 在 20 前插入 15, O(1) 操作。l: {5, 10, 15, 20, 30, 35}

6. 特有的链表操作 (Specific List Operations)

这些是 list 独有的、非常高效的操作。

  • splice(const_iterator pos, list& other, ...)

    • 功能拼接。将 other 链表中的一个或多个节点移动到当前 listpos 位置。这个过程只移动指针,不涉及元素的拷贝或移动,因此是极快的 O(1) 操作(移动整个链表)或 O(n)(移动other中N个元素)。
  • merge(list& other)

    • 功能合并。将已排序的 other 链表合并到当前已排序的 list 中,结果仍然保持有序。other 在此操作后会变为空。O(n)。
  • sort()

    • 功能:对链表进行内部排序。不能使用 std::sort(l.begin(), l.end()),因为它需要随机访问迭代器。
  • unique()

    • 功能:移除连续的重复元素。
  • reverse()

    • 功能:反转链表中元素的顺序。O(n)。
  • remove(const T& value)

    • 功能:移除所有等于 value 的元素。
  • remove_if(UnaryPredicate p)

    • 功能:移除所有使谓词 p 返回 true 的元素。

示例

std::list<int> l1 = {1, 10, 20};
std::list<int> l2 = {5, 15};

// splice 示例
auto it = l1.begin();
it++; // 指向 10
l1.splice(it, l2); // 将 l2 的所有元素移动到 l1 的 10 之前
// l1: {1, 5, 15, 10, 20}, l2: {}

// sort 和 merge 示例
std::list<int> listA = {10, 30, 5};
std::list<int> listB = {20, 4, 40};
listA.sort(); // listA: {5, 10, 30}
listB.sort(); // listB: {4, 20, 40}
listA.merge(listB); // listA: {4, 5, 10, 20, 30, 40}, listB: {}

// unique 示例
std::list<int> l3 = {1, 2, 2, 3, 3, 3, 4};
l3.unique(); // l3: {1, 2, 3, 4}

7. 非成员函数 (Non-member functions)

  • 比较运算符 (==, !=, <, >, <=, >=)

    • 功能:以字典序比较两个 list 的内容。
  • std::swap(list& a, list& b)

    • 功能:与成员函数 swap 等效。
  • std::erase(list<T>& c, const U& value) (C++20)

    • 功能:移除 c 中所有等于 value 的元素。等效于成员函数 remove
  • std::erase_if(list<T>& c, UnaryPredicate p) (C++20)

    • 功能:移除 c 中所有使一元谓词 p 返回 true 的元素。等效于成员函数 remove_if

下一个更新预告 std::deque

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值