STL 容器操作概览
链表和允许重复关键字的关联容器不提供[]
或 at()。
forward_list 不提供 insert()、erase() 或 emplace(),而是提供*_after
系列操作。
forward_list 不提供 back()、push_back()、pop_back() 或 emplace_back()。
vector 不提供 push_front()、pop_front()。
forward_list 不提供反向迭代器。
无序关联容器不提供<
、<=
、>
或>=
。
成员类型
通过类型别名,我们可以在不了解容器中元素类型的情况下使用它。
如果需要元素类型,可以使用容器的 value_type。
如果需要元素类型的一个引用,可以使用 reference 或 const_reference。
使用作用域运算符来说明我们希望使用的类型成员;例:list<string>::iterator iter;
类型别名 | 功能 |
---|---|
value_type | 元素类型 |
allocator_type | 内存管理类型 |
size_type | 容器下标、元素数目等的无符号类型 |
diffreence_type | 带符号类型,足够保存两个迭代器之间的距离 |
iterator | 行为类似value_type* |
const_iterator | 行为类似const_value_type* |
reverse_iterator | 行为类似value_type* |
const_reverse_iterator | 行为类似const_value_type* |
reference | value_type& |
const_reference | const_value_type& |
pointer | 行为类似value_type* |
const_pointer | 行为类似const_value_type* |
构造函数、析构函数和赋值操作
顺序容器定义和初始化
默认初始化
容器为空,没有任何元素。
vector <int> V{}; //容器包含 int 类型的元素,容器为空,大小为零。
deque <char> D{}; //双端队列
list <int> List{}; //双向链表
forward_list <int> L{}; //单向链表
指定容器大小
只有顺序容器(不包括 array)的构造函数接受大小参数。
只提供容器大小参数。
vector <int> V(5); //内含 5 个整数,默认值为 0
deque <char> D(6); //内含 6 个字符,默认值为 '\0'
list <double> List(11); ///内含 11 个浮点数,默认值为 0
提供容器大小,并指定显示的初始值。
vector <int> V(5, 12); //内含 5 个整数,这些元素初始值都为 12 。
deque <char> D(5,'A'); //内含 5 个字符,这些元素初始值都为 'A' 。
如果元素类型是内置类型或有默认构造函数的类类型,可以只提供容器大小参数;如果元素类型没有默认构造函数,则必须指定一个显示的初始值。
列表初始化
初始化为初始化列表中元素的拷贝,初始化列表隐含地指定了容器的大小。
vector <int> V{ 1,3,5,7,11,13,17,19 }; //可变数组
deque <char> D{ 'A','B','C' }; //双端队列
list <string> List{ "an","list","c++" }; //双向链表
forward_list <int> L{ 1,3,5,7 }; //单向链表
将一个新容器创建为另一个容器的拷贝
拷贝整个容器
vector <int> V1{1,3,5,7,11,13,17,19};
vector <int> V2{ V1 };
deque <char> D1{ 'A','B','C' };
deque <char> D2{ D1 };
拷贝一对迭代器指定范围中的元素
vector <int> V1{ 1,3,5,7,11,13,17,19 };
vector <int> V2(V1.begin() + 2, V1.end() - 2); //拷贝元素:5,7,11,13
vector <int> V3(V1.begin(), V1.end()); //拷贝容器 V1 内的所有元素
当将一个容器初始化另一个容器的拷贝时,两个容器的类型和元素类型都必须相同(或可隐式类型转换)。
容器的赋值运算
赋值运算符将其左边容器中的全部元素替换为右边容器中元素的拷贝。
赋值运算符要求左边和右边的运算对象具有相同的类型。
vector <int> V1 { 1,3,5,7,11,13,17,19 };
vector <int> V2 { 3,3,7 };
V1 = V2; // V1 内的元素变为3,3,7
V1 = { 3,4,5,6 }; // V1 的大小变为 4
assign 函数
顺序容器(array除外)还定义了一个 assign 成员,允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。用参数指定的元素(的拷贝)替换左边容器中的所有元素。
vector <int> V1{ 2,3,4 };
vector <int> V2 { 1, 3, 5, 7, 11, 13, 17, 19 };
V1.assign( V2.begin(), V2.end() ); //将V1中的元素替换为一对迭代器指定范围中的元素
V1.assign( {1,2,3,4} ); //将V1中的元素替换为列表中的元素
V1.assign( 5,12 ); //将V1中的元素替换为 5 个 12
对于一个名为 C 的容器,我们有:
成员函数 | 功能 |
---|---|
C c {}; | 默认构造函数;c 是一个空容器 |
C c {a}; | 默认构造 c;使用分配器 a |
C c (n); | c 初始化为 n 个元素,元素值为value_type{} ;关联容器不适用 |
C c (n,x); | c 初始化为 x 的 n 个拷贝;关联容器不适用 |
C c (n,x,a); | c 初始化为 x 的 n 个拷贝;使用分配器 a;关联容器不适用 |
C c {elem}; | 用 elem 初始化 c;若 C 有一个初始化器列表构造函数,优先使用它;否则,使用其它构造函数 |
C c {c2}; | 拷贝构造函数;将 c2 的元素和分配器拷贝入 c |
C c {move(c2)}; | 移动构造函数;将 c2 的元素和分配器移入 c |
C c {{elem},a}; | 用 initialzer_list{elem} 初始化 c;使用分配器 a |
C c {b,e}; | 用 [b,e) 中的元素初始化 c |
C c {b,e,a}; | 用 [b,e) 中的元素初始化 c;使用分配器 a |
c.~C(); | 析构函数;销毁 c 的元素并释放资源 |
c2 = c; | 拷贝赋值;将 c 的元素拷贝入 c2 |
c2 = move©; | 移动赋值;将 c 的元素移入 c2 |
c = {elem}; | 将 initialzer_list{elem} 中的元素赋予 c |
c.assign(n,x); | 将 x 的 n 个拷贝赋予 c;关联容器不适用 |
c.assign(b,e); | 将 [b,e) 中的元素赋予 c |
c.assign({elem}); | 将 initialzer_list{elem} 中的元素赋予 c |
以上表格中,C 是一个容器;默认情况下,C 使用分配器C::allocator_type()
。
赋值操作并不拷贝或移动分配器。
一个构造函数或是一次元素拷贝可能会抛出异常。
对大小初始化器使用()
,而对其它所有初始化器都使用{}
。
大小和容量
大小是指容器中的元素数目。
容量是指在重新分配更多内存之前,容器能够保存的元素数目。
容器大小
除了一个例外,每个容器类型都有三个与大小相关的操作。
成员函数 size() 返回容器中元素的数目。
成员函数 empty() 判断容器是否为空。
成员函数 max_size() 返回容器一个大于或等于该类型容器所容纳的最大元素数的值。
vector<int> V;
cout << V.size() << endl; //容器中元素的数目为零
cout << V.empty() << endl; //容器为空,返回 ture
cout << V.max_size() << endl;
管理容量的成员函数
成员函数 capacity() 操作告诉我们容器在不扩张内存空间的情况下可以容纳多少个元素。
成员函数 reserve() 操作允许我们通知容器它应该准备保存多少个元素。
成员函数 shrink_to_fit() 操作请求退回不需要的内存空间。
capacity() 至少与 size() 一样大
vector<char> V; //空容器,size = 0,capacity = 0
V.push_back('A');
V.push_back('B');
cout << V.size() << endl; //添加元素后,size = 2
cout << V.capacity() << endl;//添加元素后,capacity = 2
只有当需要的内存空间超过当前容量时,调用 reserve() 函数才会改变 vector 的容量。
vector<char> V; //空容器,size = 0,capacity = 0
V.reserve(5); //将 capacity 设定为 5
V.push_back('A');
V.push_back('B');
cout << V.size() << endl; //添加元素后,size = 2
cout << V.capacity() << endl;//添加元素后,capacity = 5
如果需求大小小于或等于当前容量,调用 reserve() 函数什么也不会做。
vector<char> V{ 'A','B','C','D','E','F' };
cout << V.capacity() << endl; //capacity = 6
V.reserve(4);
cout << V.capacity() << endl; //capacity = 6
改变容器大小
可以使用 resize() 来增大或缩小容器,array 不支持 resize()。
如果当前大小大于所要求的大小,容器后部的元素会被删除;
vector<int> V{ 1,2,3,4,5 };
cout << V.capacity() << endl; //capacity = 6
V.resize(3); //V容器内的元素变为:1,2,3
cout << V.capacity() << endl; //capacity = 6
如果当前大小小于新大小,会将新元素添加到容器后部。
vector<int> V{ 1,2,3,4 };
cout << V.capacity() << endl; //capacity = 4
V.resize(8, 10); //V容器内的元素变为:1,2,3,4,10,10,10
cout << V.capacity() << endl; //capacity = 8
如果元素类型是内置类型或有默认构造函数的类类型,可以只提供容器大小参数;如果元素类型没有默认构造函数,则必须指定一个显示的初始值。
成员函数 | 功能 |
---|---|
x = c.size(); | x 是 c 的元素数目 |
c.empty(); | c 是否为空 |
x = c.max_size(); | x 是 c 的最大可能元素数目 |
x = c.capacity(); | x 是为 c 分配的空间大小;只适用于 vector 和 string |
c.reserve(n); | 为 c 预留 n 个元素的空间;只适用于 vector 和 string |
c.resize(n); | 将 c 的大小改变为 n;将增加的元素初始化为默认元素值;只使用于顺序容器(和 string) |
c.resize(n,v); | 将 c 的大小改变为 n;将增加的元素初始化为 v;只适用于顺序容器(和 string) |
c.shrink_to_fit(); | 令 c.capacity() 等于 c.size();将增加的元素初始化为 v;只适用于 vector、deque 和 string |
迭代器
容器可以看作按容器迭代器定义的顺序或相反的顺序排列的元素序列。
使用范围 for 进行元素遍历
vector <int> V{ 1,3,5,7,11,13,17,19 };
for (auto i : V) //隐式使用 v.begin() 和 v.end()
cout << i << ' ';
使用迭代器进行元素遍历
vector <int> V{ 1,3,5,7,11,13,17,19 };
for (auto iter = V.cbegin(); iter != V.cend(); ++iter)
{
cout << *iter << ' ';
}
成员函数 | 功能 |
---|---|
p = c.begin(); | p 指向 c 的首元素 |
p = c.end(); | p 指向 c 的尾后元素 |
p = c.cbegin(); | p 指向 c 的首元素,常量迭代器 |
p = c.cend(); | p 指向 c 的尾后元素,常量迭代器 |
p = c.rbegin(); | p 指向 c 的反序的首元素 |
p = c.rend(); | p 指向 c 的反序的尾后元素 |
p = c.crbegin(); | p 指向 c 的反序的首元素,常量迭代器 |
p = c.crend(); | p 指向 c 的反序的尾后元素,常量迭代器 |
元素访问
包括 array 在内的每个顺序容器都有一个 front 成员函数,除 forward_list 以外的所有顺序容器都有一个 back 成员函数。
这两个操作分别返回首元素和尾元素的引用。
vector <char> V{ 'A','B','C','D' };
char C1 = V.front(); //获取首元素的拷贝
C1 = 'Z'; //未改变首元素的值
char & C2 = V.front(); //获取首元素的引用
C2 = 'F'; //首元素的值变为 'F'
char& C3 = V.back(); //获取尾元素的引用
C3 = 'E'; //尾元素的值变为 'E'
对一个空容器调用 front 和 back,就象使用一个越界的下标一样,是一种严重的程序设计错误。
下标操作和安全的随机访问
提供快速随机访问的容器都提供下标运算符。
给定的下标必须大于等于 0,且小于容器的大小。
vector <char> V{ 'A','B','C','D' };
for (unsigned int i = 0; i < 4; i++)
{
cout << V[i] << ' '; //下标访问
}
at 成员函数类似下标运算符,但如果下标越界,at 会抛出一个 out_of_range 异常。
vector <char> V{ 'A','B','C','D' };
for (unsigned int i = 0; i < 4; i++)
{
cout << V.at(i) << ' '; // at 成员函数访问
}
在容器中访问元素的成员函数(front、back、下标 和 at)返回的都是引用。
vector <char> V{ 'A','B','C','D' };
V[2] = 'Z'; //改变元素V[2]的值
V.at(3) = 'N'; //改变元素V[3]的值
如果容器是一个 const 对象,则返回值是 const 对象的引用。
成员函数 | 功能 |
---|---|
c.front(); | 指向 c 的首元素;关联容器不适用 |
c.back(); | 指向 c 的尾元素;forward_list 和关联容器不适用 |
c[i]; | 指向 c 的第 i 个元素;不进行范围检查;链表和关联容器不适用 |
c.at(i); | 指向 c 的第 i 个元素;若 i 超出范围,则抛出一个 out_of_range;链表和关联容器不适用 |
栈操作
push_back()
成员函数 push_back() 将一个元素追加到一个顺序容器的尾部。
vector <int> V; //可以先定义一个空的容器
V.push_back(4); //然后向容器的尾部添加元素
V.push_back(5);
push_front()
成员函数 push_front() 将元素插入到容器头部。
forward_list <char> L; //可以先定义一个空的容器
L.push_front('A'); //然后向容器的首部添加元素
L.push_front('B');
L.push_front('C');
pop_front() 和 pop_back()
成员函数 pop_front() 和 pop_back() 分别删除首元素和尾元素。
deque <char> D{ 'A','B','C','D' };
char C1 = D.front(); //保存首元素
D.pop_front(); //弹出首元素
char C2 = D.back(); //保存尾元素
D.pop_back(); //弹出尾元素
pop_front() 和 pop_back() 操作返回 void;弹出元素之前,最好保存它。
不能对一个空容器执行弹出操作。
成员函数 | 功能 |
---|---|
c.push_back(x); | 将 x 添加到 c 的尾元素之后 |
c.pop_back(x); | 删除 c 的尾元素 |
c.push_front(x) | 将 x 添加到 c 的首元素之前 |
c.pop_front() | 删除 c 的首元素 |
c.emplace_back(args); | 用 args 构造一个对象,将它添加到 c 的尾元素之后 |
c.emplace_front(args) | 将 T{args} 添加到 c 的首元素之前 |
列表操作
插入元素
insert() 成员提供更一般的添加功能,它允许我们在容器中任意位置插入 0 个或多个元素。
在迭代器指向的元素之前插入一个值。
list <char> L{ 'A','B','C','D' };
for (auto it = L.begin(); it != L.end(); ++it )
{
if ( *it == 'B' )
{//在元素'B'之前,插入元素'Z'
L.insert( it,'Z' );
break;
}
}
在迭代器指向的元素之前插入 n 个相同的值;若 n 为零,insert 函数返回第一个参数。
list <char> L{ 'A','B','C','D' };
for (auto it = L.begin(); it != L.end(); ++it )
{
if ( *it == 'B' )
{//在元素'B'之前,插入 4 个'i'
L.insert( it,4,'i' );
break;
}
}
在迭代器指向的元素之前插入一个花括号包围的元素值列表;若元素值列表为空,insert 函数返回第一个参数。
list <char> L{ 'A','B','C','D' };
for (auto it = L.begin(); it != L.end(); ++it )
{
if ( *it == 'B' )
{//在元素'B'之前,插入元素'a','b','c'
L.insert( it, {'a','b','c'} );
break;
}
}
在迭代器指向的元素之前插入一对迭代器指定范围的所有元素;第一个迭代器指向要插入的第一个元素,第二个迭代器指向要插入的最后一个元素之后的位置。
如果范围为空,不插入任何元素,insert() 函数返回第一个参数。
list <char> L1{ 'a','b','c' };
list <char> L2{ 'A','B','C','D' };
for (auto it = L2.begin(); it != L2.end(); ++it )
{
if ( *it == 'B' )
{//在元素'B'之前,插入列表L1内的所有元素。
L2.insert( it,L1.begin(), L1.end() );
break;
}
}
insert() 函数返回指向第一个新加入元素的迭代器。
char L1[] = {'a','b','c'};
list <char> L2{ 'A','B','C','D' };
auto it = L2.begin();
for ( unsigned int i = 0; i < 3; ++i )
{//在 L2 列表头部先后插入元素'a','b','c'
it1 = L2.insert( it, L1[i] );
}
如果传递给 insert() 一对迭代器,它们不能指向添加元素的目标容器。
使用 emplace() 操作
新标准引入了三个新成员——emplace_front()、emplace() 和 emplace_back(),这些操作是构造而不是拷贝元素;这些操作分别对应 push_front()、insert() 和 push_back()。
当调用 push 或 insert() 成员函数时,我们将元素类型的对象传递给他们,这些对象被拷贝到容器中。
当调用顺序容器的 empalce 成员函数时,则是将参数传递给元素类型的构造函数;empalce 成员使用这些参数在容器管理的内存空间中直接构造元素。
emplace 函数的参数根据元素类型而变化,参数必须与元素的构造函数相匹配。
删除元素
成员函数 erase() 从容器中删除迭代器指定的元素。
list <char> L{ 'A','B','C','D','E' };
for (auto it = L.begin(); it != L.end(); ++it )
{
if ( *it == 'C' ) //删除指定的元素
{
it = L.erase(it);
cout << *it << endl; //输出被删除的元素之后位置的迭代器。
break;
}
}
成员函数 erase() 删除一对迭代器指定范围内的所有元素;第一个迭代器指向被删除的第一个元素,第二个迭代器指向被删除的最后一个元素之后的位置。
list <char> L{ 'A','B','C','D','E' };
for (auto it = L.begin(); it != L.end(); ++it )
{
if ( *it == 'D' ) //迭代器指向被删除元素之后的位置
{
L.erase( L.begin(), it ); //删除元素'A','B','C'
break;
}
}
两个版本的 erase() 函数返回指向被删除的元素(或最后一个元素)之后位置的迭代器。
删除容器内所有的元素
成员函数 clear() 删除容器内所有元素。
list <char> L{ 'A','B','C','D','E' };
L.clear(); //与 L.erase( L.begin(), L.end()); 等价
成员函数 | 功能 |
---|---|
q = c.insert(p,x); | 将 x 插入到 p 之前 |
q = c.insert(p,n,x); | 在 p 之前插入 x 的 n 个拷贝;若 c 是一个关联容器,p 并非插入位置,而是提示搜索开始位置 |
q = c.insert(p,first,last); | 将 [first:last) 中的元素插入到 p 之前,不适用于关联容器 |
q = c.insert(p,{elem}); | 将 initialzer_list{elem} 中的元素插入到 p 之前,p 提示从哪里开始搜索放置新元素的位置 |
q = c.emplace(p,args); | 用 args 创建新元素,插入到 p 之前,不适用于关联容器 |
q = c.erase§; | 将位于 p 处的元素从 c 中删除 |
q = c.erase(first,last); | 从 c 中删除 [first:last) 间的元素 |
c.clear(); | 删除 c 的所有元素 |
比较操作
关系运算符
每个容器类型都支持相等运算符(==
和!=
);除了无序关联容器外的所有容器都支持关系运算符(>
、>=
、<
、<=
)。
比较两个容器实际上是进行元素的逐对比较:
- 如果两个容器元素数目相同且所有元素都两两对应相同等,则这两个容器相等。
- 如果两个容器元素数目不同,但较小容器中的每个元素都等于较大容器中的对应元素,则较小容器小于较大容器。
- 如果两个容器都不是另一个容器的前缀子序列,则比较它们的结果取决于第一个不想等的元素的比较结果。
vector <int> V1 { 1, 3, 5, 7, 11 };
vector <int> V2{ 1, 3, 5 };
vector <int> V3{ 1, 3, 5, 7, 11 };
vector <int> V4{ 1, 7, 3 };
cout << ( V2 < V1 ) << endl; //true,每个元素都相等,但 V2 中元素数目更少
cout << ( V1 == V3 ) << endl; //true,每个元素都相等,且 V1 和 V3 大小相同
cout << ( V3 < V4 ) << endl; //true,V3 和 V4 在元素[1]处不同,且 V3[1] < V4[1]
关系运算符左右两边的运算对象必须是相同类型的容器,且必须保存相同类型的元素。
只有当其元素类型也定义了相应的比较运算符时,我们才可以使用关系运算符来比较容器。
swap()
swap() 操作交换两个相同类型的容器的内容;调用 swap() 函数后,两个容器的元素将会交换:
vector <int> V1{ 2,3,4 };
vector <int> V2 { 1, 3, 5, 7, 11, 13, 17, 19 };
swap(V1,V2);
/*交换后:
V1 包含八个元素:1, 3, 5, 7, 11, 13, 17, 19
V2 包含三个元素:2,3,4
*/
除 array 外,swap() 不对任何元素进行拷贝、删除或插入操作。
交换两个容器内容的操作会很快,swap() 只是交换了两个容器的内部数据结构。
swap() 操作两个 array 会真正交换它们的元素。
成员函数 | 功能 |
---|---|
c1 == c2 | c1 的所有元素都与 c2 的对应元素相等吗? |
c1 != c2 | !(c1 == c2) |
c1 < c2 | 按字典顺序,c1 在 c2 之前吗? |
c1 <= c2 | !(c1 > c2) |
c1 > c2 | 按字典顺序,c1 在 c2 之后吗? |
c1 >= c2 | !(c1 < c2) |
c1.swap(c2) | 交换 c1 和 c2 的值;不抛出异常 |
swap(c1,c2) | c1.swap(c2) |
特殊的 forward_list 操作
当在 forward_list 中添加或删除元素时,我们必须关注两个迭代器:一个指向我们要处理的元素,另一个指向其前驱。
forward_list 定义了 before_begin() 成员函数,它返回一个首前迭代器(这个迭代器不能解引用)。
这个迭代器允许我们在链表首元素之前并不存在的元素“之后”添加或删除元素。(即在链表首元素之前添加删除元素。)
成员函数 insert_after() 在迭代器指向的元素之后插入元素;返回一个指向最后一个插入元素的迭代器。
vector <int> v{ 6,8,10 };
forward_list <int> list{ 1,3,5,7,9 };
auto it = list.begin();
list.insert_after( it,12 ); //插入一个元素
list.insert_after(it,v.begin(),v.end()); //插入 n 个相同的元素
list.insert_after( it, {0,2,4} ); //插入一对迭代器范围内的元素
list.insert_after(it, 3, 11); //插入花括号列表内的元素
成员函数 erase_after() 删除迭代器指向的元素之后的元素;返回一个指向被删除的最后一个元素之后元素的迭代器。
forward_list <int> list{ 1,3,5,7,9 };
auto it = list.begin();
list.erase_after( it ); //删除 3
// list.erase_after(list.begin(),list.end());
在迭代器指向的元素之前插入元素。
vector <int> v{ 6,8,10 };
forward_list <int> list{ 1,3,5,7,9 };
auto it = list.before_begin(); //首前迭代器
list.insert_after( it,12 );
list.insert_after(it,v.begin(),v.end());
list.insert_after( it, {0,2,4} );
list.insert_after(it, 3, 11);
成员函数 | 功能 |
---|---|
p2 = c.emplace_after(p,args); | 用 args 构造一个元素,插入到 p 之后;p2 指向新的元素 |
p2 = c.insert_after(p,x); | 在 p 之后插入 x ;p2 指向新的元素 |
p2 = c.insert_after(p,n,x); | 在 p 之后插入 x 的 n 个拷贝;p2 指向新的元素 |
p2 = c.insert_after(p,b,e); | 在 p 之后插入 [b:e) 间的元素;p2 指向最后一个新元素 |
p2 = c.insert_after(p,{elem}); | 在 p 之后插入 {elem} 中的元素;p2 指向最后一个新元素;elem 是一个 initialzer_list |
p2 = c.erase_after§; | 删除 p 之后的元素;p2 指向 p 之后的元素或 lst.end() |
p2 = c.erase_after(b,e); | 删除 [b:e) 间的元素;p2 = e |
lst.splice_after(p,lst2) | 在 lst2 中 p 之后的位置进行切片 |
lst.splice_after(p,b,e) | 在 [b:e] 间 p 之后的位置进行切片 |
lst.splice_after(p,lst2,p2) | 在 p2 中 p 之后的位置进行切片;从 lst2 中删除 p2 |
lst.splice_after(p,lst2,b,e) | 在 [b:e] 间 p 之后的位置进行切片;从 lst2 中删除 [b:e) |
forward_list 无法访问迭代器之前的元素,因此 emplace()、insert()、erase() 和 splice() 操作作用于迭代器之后的位置。
特殊的 list 操作
splice() 操作不会拷贝元素值,也不会令指向元素的迭代器失效。
成员函数 | 功能 |
---|---|
lst.splice(p,lst2) | 将 lst2 的元素插入到 p 之前;lst2 变为空 |
lst.splice(p,lst2,p2) | 将 p2 指向的 lst2 中的元素插入到 p 之前;该元素从 lst2 中删除 |
lst.splice(p,lst2,b,e) | 将 [b:e) 指向的 lst2 中的元素插入到 p 之前;该元素从 lst2 中删除 |
list 和 forward_list 的共同操作
除了下标操作、容量管理以及 forward_list 不提供 size() 外,STL 链表提供与 vector 相同的成员类型和操作。
此外,list 和 forward_list 还提供特殊的链表成员函数:
成员函数 | 功能 |
---|---|
lst.remove(v) | 删除 lst 中所有等于 v 的元素 |
lst.remove_if(v) | 删除 lst 中所有满足f(x) == true 的元素 |
lst.unique() | 删除 lst 中所有的相邻重复元素 |
lst.unique(f) | 删除 lst 中所有的相邻重复元素,用 f 进行相等判定 |
lst.merge(lst2) | 合并有序链表 lst 和 lst2,用 < 确定序;将 lst2 合并入 lst,然后将其清空 |
lst.merge(lst2,f) | 合并有序链表 lst 和 lst2,用 f 确定序;将 lst2 合并入 lst,然后将其清空 |
lst.sort() | 排序 lst ,用 < 确定序 |
lst.sort(f) | 排序 lst ,用 f 确定序 |
lst.reverse() | 反转 lst 中的元素顺序,不抛出异常 |
与通用算法 remove() 和 unique() 相比,成员函数版本会影响链表的大小。
merge() 算法是稳定的,即相等的元素会保持相对顺序。