List
列表 (list) 简介
列表 (list) 是一种线性数据结构,这意味着列表中的元素排列成一个序列。每个元素在列表中都有一个确定的位置,并且元素之间存在着先后关系。
在计算机科学中,列表通常通过链表 (linked list) 的方式来实现。链表是一种由一系列节点组成的数据结构。每个节点包含两部分:
- 数据 (information/info):用于存储实际的元素值。
- 指针 (pointer/next):指向列表中的下一个节点。对于双向链表 (doubly linked list),每个节点还会包含一个指向前一个节点的指针 (prev)。
链表有多种变体:
- 单向链表 (singly linked list):每个节点只有一个指向下一个节点的指针。要访问链表中的元素,通常需要从头节点 (head) 开始遍历。
- 双向链表 (doubly linked list):每个节点有两个指针,一个指向下一个节点,一个指向上一个节点。这使得在列表中进行双向遍历更为方便。
- 循环链表 (circular list):最后一个节点的指针指向头节点,形成一个环。循环链表可以是单向的也可以是双向的。
链表与数组等其他线性数据结构相比,具有以下特点:
- 动态性:链表的大小可以在运行时动态地增加或减少,因为节点可以在需要时被分配或释放。
- 插入和删除效率高:在链表的任意位置插入或删除一个节点通常只需要修改相邻节点的指针,时间复杂度为 O(1) (假设已知要插入或删除的位置)。
- 随机访问效率低:要访问链表中特定位置的元素,通常需要从头节点开始遍历,直到找到目标位置,时间复杂度为 O(n),其中 n 是链表的长度。
您的资料还提到了 C++ 标准模板库 (STL) 中的 list
。STL 中的 list
是一个双向链表。它提供了一系列方便的成员函数来操作列表,例如插入 (insert
, push_front
, push_back
)、删除 (erase
, pop_front
, pop_back
, remove
, remove_if
, clear
)、访问元素 (front
, back
)、排序 (sort
)、合并 (merge
) 等。STL list
的设计使得在列表中进行插入和删除操作非常高效。
总而言之,列表是一种常用的线性数据结构,它通常通过链表来实现,链表由相互连接的节点组成,每个节点存储数据和指向下一个(或上一个)节点的指针。链表具有动态性和高效的插入删除操作的优点,但在随机访问方面效率较低。C++ STL 提供了方便易用的 list
容器,它是一个双向链表的实现。
好的,根据您提供的资料,特别是第三章第七节“Lists in the Standard Template Library”,以下是以表格方式列出的 std::list
的常用成员函数及其操作,以及一个演示程序。
list 常用成员函数
成员函数 | 操作 | 来源 |
---|---|---|
list() | 构造一个空列表。 | |
list(size_type n, const T& el = T()) | 构造一个包含 n 个 el 副本的列表 (如果未提供 el ,则使用默认构造函数 T() )。 |
|
list(iterator first, iterator last) | 构造一个包含由迭代器 first 和 last 指示范围内的元素的列表。 |
|
list(const list<T>& lst) | 复制构造函数。 | |
begin() | 返回一个指向列表第一个节点的迭代器。 | |
const_begin() const | 返回一个指向列表第一个节点的常量迭代器。 | |
end() | 返回一个指向列表最后一个节点之后位置的迭代器。 | |
const_end() const | 返回一个指向列表最后一个节点之后位置的常量迭代器。 | |
clear() | 移除列表中的所有节点。 | |
empty() const | 如果列表不包含任何节点则返回 true ,否则返回 false 。 |
|
erase(iterator i) | 移除迭代器 i 所引用的节点,并返回一个引用被移除元素之后元素的迭代器。 |
|
erase(iterator first, iterator last) | 移除由迭代器 first 和 last 指示范围内的节点,并返回一个引用被移除的最后一个元素之后元素的迭代器。 |
|
front() | 返回列表中第一个节点的元素。 | |
const front() const | 返回列表中第一个节点的常量元素。 | |
insert(iterator i, const T& el = T()) | 在迭代器 i 引用的节点之前插入元素 el ,并返回一个引用新插入节点的迭代器。 |
|
insert(iterator i, size_type n, const T& el) | 在迭代器 i 引用的节点之前插入 n 个 el 的副本。 |
|
insert(iterator i, iterator first, iterator last) | 在迭代器 i 引用的节点之前插入由迭代器 first 和 last 指示范围内的元素。 |
|
max_size() const | 返回列表中可能包含的最大节点数。 | |
merge(list<T>& lst) | 对于已排序的当前列表和 lst ,移除 lst 中的所有节点并将它们按排序顺序插入到当前列表中。 |
|
merge(list<T>& lst, Comp f) | 对于已排序的当前列表和 lst ,移除 lst 中的所有节点,并根据二元布尔函数 f() 指定的排序顺序插入到当前列表中。 |
|
pop_back() | 移除列表的最后一个节点。 | |
pop_front() | 移除列表的第一个节点。 | |
push_back(const T& el) | 在列表的末尾插入元素 el 。 |
|
push_front(const T& el) | 在列表的开头插入元素 el 。 |
|
remove(const T& el) | 从列表中移除所有包含元素 el 的节点。 |
|
remove_if(Pred f) | 移除所有使得一元布尔函数 f() 返回 true 的节点。 |
|
resize(size_type n, const T& el = T()) | 使列表包含 n 个节点,如果当前大小小于 n ,则添加 n - size() 个包含元素 el 的节点;如果当前大小大于 n ,则丢弃多余的节点。 |
|
sort() | 以升序对列表中的元素进行排序。 | |
sort(Comp f) | 根据二元布尔函数 f() 指定的顺序对列表中的元素进行排序。 |
|
splice(iterator i, list<T>& lst) | 移除列表 lst 中的所有节点,并将它们插入到当前列表中迭代器 i 所指示的位置之前。 |
|
splice(iterator i, list<T>& lst, iterator j) | 移除列表 lst 中迭代器 j 所引用的节点,并将其插入到当前列表中迭代器 i 所指示的位置之前。 |
|
splice(iterator i, list<T>& lst, iterator first, iterator last) | 移除列表 lst 中由迭代器 first 和 last 指示范围内的节点,并将它们插入到当前列表中迭代器 i 所指示的位置之前。 |
|
swap(list<T>& lst) | 将当前列表的内容与另一个列表 lst 的内容进行交换。 |
list 演示程序
以下程序示例了 std::list
的一些常用操作:
#include <iostream>
#include <list>
#include <string>
#include <algorithm> // 需要使用 std::find
using namespace std;
// 用于 remove_if 的谓词
bool isShort(const string& s) {
return s.length() < 5;
}
// 用于 sort 的比较函数
bool compareLength(const string& s1, const string& s2) {
return s1.length() < s2.length();
}
int main() {
// 构造列表
list<string> my_list1;
my_list1.push_back("apple");
my_list1.push_front("banana");
my_list1.push_back("orange");
my_list1.push_front("grape");
cout << "初始列表 my_list1: ";
for (const string& s : my_list1) {
cout << s << " ";
}
cout << endl;
// 插入元素
list<string>::iterator it = find(my_list1.begin(), my_list1.end(), "orange");
if (it != my_list1.end()) {
my_list1.insert(it, "kiwi");
}
cout << "在 'orange' 前插入 'kiwi' 后的 my_list1: ";
for (const string& s : my_list1) {
cout << s << " ";
}
cout << endl;
// 删除元素
my_list1.pop_front();
my_list1.remove("apple");
cout << "移除首元素和 'apple' 后的 my_list1: ";
for (const string& s : my_list1) {
cout << s << " ";
}
cout << endl;
// 使用 remove_if
my_list1.remove_if(isShort);
cout << "移除长度小于 5 的字符串后的 my_list1: ";
for (const string& s : my_list1) {
cout << s << " ";
}
cout << endl;
// 排序
my_list1.sort(compareLength);
cout << "按长度排序后的 my_list1: ";
for (const string& s : my_list1) {
cout << s << " ";
}
cout << endl;
// 清空列表
my_list1.clear();
cout << "清空 my_list1 后,是否为空? " << my_list1.empty() << endl;
// 构造第二个列表
list<string> my_list2 = {"zebra", "yak"};
// 使用 splice
list<string> my_list3 = {"cat", "dog", "elephant"};
list<string>::iterator it_splice = next(my_list3.begin()); // 指向 "dog"
my_list3.splice(it_splice, my_list2);
cout << "将 my_list2 拼接 (splice) 到 my_list3 的 'dog' 之前: ";
for (const string& s : my_list3) {
cout << s << " ";
}
cout << endl;
return 0;
}
程序说明:
- 我们包含了
<iostream>
用于输入输出,<list>
使用std::list
容器,<string>
使用字符串,<algorithm>
使用std::find
查找元素。 - 创建了几个
std::list<string>
类型的列表my_list1
、my_list2
和my_list3
,并使用push_back
和push_front
添加了一些初始元素。 - 演示了如何使用迭代器和
find
函数在列表中查找特定元素,并使用insert
在找到的元素之前插入新的元素 “kiwi”。 - 展示了
pop_front
(移除首元素)和remove
(移除指定值的元素)的用法。 - 使用了
remove_if
函数,它接受一个谓词函数isShort
,用于移除列表中所有长度小于 5 的字符串。 - 使用
sort
函数对列表进行排序,这里我们提供了一个自定义的比较函数compareLength
,按字符串的长度进行排序。 - 展示了
clear
函数用于移除列表中的所有元素,以及empty
函数用于检查列表是否为空。 - 创建了
my_list2
和my_list3
,并使用splice
函数将my_list2
中的所有元素移动到my_list3
中指定迭代器位置之前。注意,splice 操作会将源列表中的元素移除。
这个示例程序涵盖了 std::list
中一些最常用的成员函数,帮助您理解它们的基本用法。您可以编译并运行此程序以查看实际效果。