C++ List

2025 年 8 月 29 日 | 阅读 14 分钟

在 C++ 中,std::list 是一个序列容器,它允许元素非连续存储。它实现为 双向链表,其中每个元素都包含指向下一个和上一个列表元素的地址。它允许我们在非连续内存中存储数据,这在已知位置时可以快速地在任何位置插入和删除元素。

与包含连续内存中元素并允许快速随机访问的 std::vector 不同,list 提供顺序访问支持,这意味着元素必须通过从前到后遍历来访问。

std::list 支持双向访问,并为插入和删除操作提供了一种有效的方法。但是,列表的遍历速度很慢,因为列表元素是按顺序访问的,而 vector 支持随机访问。

语法

它具有以下语法:

在这个语法中,

  • type: 表示列表中元素的类型。
  • list_name: 表示分配给列表的名称。

初始化列表

列表可以通过两种方式进行初始化。

C++ 声明和初始化列表示例

让我们举一个例子来说明如何在 C++ 中声明和初始化列表。

示例

编译并运行

输出

10 20 30

说明

在此示例中,我们使用多种方式声明和初始化 std::list,包括使用初始化列表、指定重复值以及从另一个列表复制。之后,我们使用基于范围的 for 循环来遍历和打印 list2 的元素。

C++ 列表基本操作

在 C++ 中,std::list 有几种操作。一些主要操作如下:

1) push_back() 和 push_front()

在 C++ 中,push_back() 函数将元素附加到末尾,push_front() 函数在开头插入。它适用于队列和双端队列之类的行为。

C++ push_back() 和 push_front() 函数示例

让我们举一个例子来说明 C++ 中的 push_back() 和 push_front() 函数。

示例

编译并运行

输出

Initial list: 
After push_back(30): 30 
After push_front(10): 10 30 
After push_back(40): 10 30 40 
After push_front(5): 5 10 30 40

说明

在此示例中,我们通过使用 push_front() 和 push_back() 函数在开头和末尾插入元素来演示 std::list 容器。之后,我们有一个 printList 函数,该函数在每次插入后用于显示列表的当前状态以及自定义消息。

2) pop_front() 和 pop_back()

在 C++ 中,pop_front() 函数用于删除列表中的第一个元素,pop_back() 函数用于删除列表中的最后一个元素。这些函数也用于从任一端收缩列表。

使用 pop_front() 和 pop_back() 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 中的 pop_front() 和 pop_back() 函数。

示例

编译并运行

输出

Original list: 10 20 30 40 50 
After pop_front(): 20 30 40 50 
After pop_back(): 20 30 40 
After another pop_back(): 20 30 

说明

在此示例中,我们演示了如何使用 pop_front() 和 pop_back() 函数从 std::list 中删除元素。之后,printList 函数显示了每次操作后的列表。首先,列表包含五个元素,然后使用 pop_front() 和 pop_back() 函数从开头和末尾删除元素,以显示列表如何动态变化。

3) insert()

在 C++ 中,我们可以使用迭代器在任何地方插入元素。它允许我们在特定位置之前添加新元素。

使用 insert() 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 中的 insert() 函数。

示例

编译并运行

输出

Initial list: 10 20 40 
After insert(15) before 20: 10 15 20 40 
After insert (50) at end: 10 15 20 40 50 
After insert(5) at the beginning: 5 10 15 20 40 50 

说明

在此示例中,我们使用迭代器演示了将元素插入到 std::list 的特定位置的过程。它以一个初始列表 {10, 20, 40} 开始,然后使用迭代器在 20 之前插入 15。之后,我们使用 end() 迭代器将 50 插入到末尾,并使用 begin() 迭代器将 5 插入到开头。最后,printList 函数显示了每次插入后列表,以显示更新的元素顺序。

4) erase()

在 C++ 中,erase() 函数用于删除给定位置或范围的元素。之后,基于迭代器的删除可以精确控制。

使用 erase() 函数的 C++ 列表示例

让我们举一个例子来说明在 C++ 中使用 erase() 函数的 erase() 函数。

示例

编译并运行

输出

Original list: 5 10 15 20 25 30 
After erasing element at position 2 (10): 5 15 20 25 30 
After erasing elements from 20 up to 30: 5 15 30 

解释

在此示例中,我们演示了如何在 C++ 中使用 std::list 的 erase() 函数删除元素。首先,它初始化一个列表 {5, 10, 15, 20, 25, 30}。之后,使用迭代器删除第二个元素 (10)。最后,我们使用迭代器 erase(it, it2) 删除从 20 到 30 的元素范围。printList 函数在每次删除后显示列表的状态。

5) size() 和 empty()

在 C++ 中,size() 函数用于返回元素的数量,empty() 函数检查列表是否为空。它对于条件检查和循环非常有用。

使用 size() 和 empty() 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 列表中 size() 和 empty() 函数。

示例

编译并运行

输出

Initially: Size = 0. Is empty? Yes
After adding elements: Size = 2, Is empty? No

说明

在此示例中,我们演示了如何使用列表容器的 size() 和 empty() 成员函数。首先,我们创建一个空列表,并显示其大小和是否为空。之后,使用 push_back() 函数添加两个整数 (100 和 200)。

6) clear()

在 C++ 中,clear() 方法主要用于从列表中删除所有元素,使列表变为空。这对于在不重新分配的情况下重用列表很有用。

使用 clear() 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 列表中的 clear() 函数。

示例

编译并运行

输出

Before clear(), size = 5
After clear(), size = 0

说明

在此示例中,我们演示了 std::list 容器的 clear() 函数。它以一个初始化为 5 个整数的列表开始。之后,在调用 clear() 函数之前和之后打印列表的大小,该函数会删除列表中的所有元素。调用 clear() 函数后,列表变为空,大小为 0。

7) sort()

在 C++ 中,sort() 函数主要用于按升序对列表进行排序。之后,它仅适用于可排序的数据类型。

使用 sort() 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 列表中 sort() 函数。

示例

编译并运行

输出

Before sort: 40 10 50 20 30 
After sort: 10 20 30 40 50 

说明

在此示例中,我们演示了如何使用 sort() 成员函数对 std::list 进行排序。首先,列表包含未排序的元素 {40, 10, 50, 20, 30}。调用 myList.sort() 函数后,列表按升序排列为 {10, 20, 30, 40, 50} 并显示。

9) reverse()

在 C++ 中,reverse() 函数用于反转列表中元素的顺序。它不返回任何内容,但会在原地修改。

使用 reverse() 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 中的 reverse() 函数。

示例

编译并运行

输出

Before reverse: 10 20 30 40 
After reverse: 40 30 20 10 

说明

在此示例中,我们演示了如何使用 reverse() 函数反转列表的元素顺序。首先,列表包含 {10, 20, 30, 40} 元素。调用 myList.reverse() 函数后,列表顺序变为 {40, 30, 20, 10},然后显示。

9) remove(value)

在 C++ 中,remove(value) 函数用于删除所有等于指定值的元素。这是删除重复项或不需要的值的有效方法。

使用 remove (Value) 函数的 C++ 列表示例

让我们举一个例子来说明 C++ 列表中的 remove (value) 函数。

示例

编译并运行

输出

Original list: 10 20 10 30 10 40 
After removing all 10s: 20 30 40 

说明

在此示例中,我们演示了如何从列表中删除特定值的​​所有出现。最初,列表包含 {10, 20, 10, 30, 10, 40} 元素。之后,调用 remove(10) 函数会删除列表中的所有 10 值,结果为 {20, 30, 40},然后显示。

C++ 列表函数

C++ 列表有几种函数。它们如下:

方法描述
insert()在迭代器指向的位置之前插入新元素。
push_back()将新元素添加到 vector 的末尾。
push_front()将新元素添加到开头。
pop_back()删除最后一个元素。
pop_front()删除第一个元素。
empty()检查列表是否为空。
size()查找列表中存在的元素数量。
max_size()查找列表的最大大小。
front()返回列表的第一个元素。
back()返回列表的最后一个元素。
swap()交换两个列表(当两个列表的类型相同时)。
reverse()反转列表的元素。
sort()按递增顺序对列表元素进行排序。
merge()合并两个已排序的列表。
splice()将一个新列表插入到调用列表中。
unique()删除列表中的所有重复元素。
resize()更改列表容器的大小。
assign()将新元素分配给列表容器。
emplace()在指定位置插入新元素。
emplace_back()将新元素添加到 vector 的末尾。
emplace_front()将新元素添加到列表的开头。

显示各种列表函数的 C++ 示例程序

让我们举一个例子来说明 C++ 列表中的各种函数。

示例

编译并运行

输出

Front: 0, Back: 5
Size: 8, Max Size: 384307168202282325
Is Empty: No
Final list4 after swap (was list1): 50 60 0 1 3 4 5 6 8 10 10 10 99 99 
Final list1 after swap (was list4): 100 200

说明

在此示例中,我们演示了如何使用多种函数来操作 std::list,包括 insert()、emplace()、splice()、sort()、merge() 等。每个方法都显示了一个特定的列表操作,例如插入、删除、修改或合并列表。之后,swap() 方法交换两个列表的内容,并反映它们之间数据的完整更改和传输。

C++ 列表 MCQs

1) 下列哪个语句符合 C++ 中 std::list 的 splice() 函数的功能?

  1. 它根据条件测试列表中的每个项目,并删除符合条件的。
  2. 它将一个列表中的每个元素复制到另一个列表中。
  3. 它可以快速地将元素从一个列表移动到另一个列表,而无需复制或移动它们。
  4. 它删除指定范围的元素,将它们保存为单独的列表并返回新列表。
 

答案: c) 它可以快速地将元素从一个列表移动到另一个列表,而无需复制或移动它们。


2) 当我们将 unique() 函数应用于一个重复项不相邻的列表时,它返回什么?

  1. 它删除相同元素的所有出现,无论它最初出现在列表中的哪个位置。
  2. 此算法仅删除列表中重复元素的第一个匹配项。
  3. 排序后,代码删除列表中出现次数多于一次的所有项。
  4. 它仅删除紧邻的重复元素。
 

答案: d) 它仅删除紧邻的重复元素。


3) 当两个 std::list 容器与 merge() 函数一起使用时,该函数执行什么操作?

  1. 将第二个列表添加到第一个列表的末尾,而不考虑列表的排列方式。
  2. 将两个已排序的列表合并成另一个单一的已排序列表,数据已按顺序排列。
  3. 在不干预的情况下安排两个列表,然后合并它们。
  4. 生成一个新列表,其中包含从两个原始列表中按降序排列的元素。
 

答案: b) 将两个已排序的列表合并成另一个单一的已排序列表,数据已按顺序排列。


4) 在 C++ 中选择容器时,何时应考虑使用 std::vector 而不是 std::list?

  1. 如果代码必须频繁地在容器的末尾插入和删除项目。
  2. 如果我们发现需要多次组织元素。
  3. 当我们需要使用索引号访问数组中的元素时。
  4. 当我们希望集合根据其内容进行扩展或收缩时。
 

答案: c) 当我们希望使用索引号访问数组中的元素时。


5) 如果我们对自定义对象的列表进行排序而没有声明任何比较函数,会发生什么?

  1. 程序将根据分配给它们的内存地址来组织对象。
  2. 当程序中不存在小于号运算符 (<) 时,会生成编译时错误。
  3. 列表不会被排序,将保持不变。
  4. 运行时会引发错误,因为我们忘记包含比较检查。
 

答案: b) 当程序中不存在小于号运算符 (<) 时,会生成编译时错误。


下一主题C++ Stack