对于STL库中的容器来说,添加元素是一个容器最基本的要求。今天我们就来沉浸式学习为list容器添加元素。在那节《初识STL库中的list容器》(进入该页,ctrl+f5查找"插入"就能获取我们需要的函数)我们以表格的形式展示了list容器内的所有成员函数,我们可以两页并用,边查看边使用。
头插尾插(push_front()、push_back()不必多说;emplace_front()、emplace_back()也是头插尾插,但是是直接构造,为前者的“高效版”;当然,如果说按位置插入,参数有位置迭代器的话:insert()可插入单个或多个元素,emplace()只能插入单个元素;由于list的独特结构(指针链接数据),使其能够使用splice()进行链表之间的“拼接”,实现“移花接木”的效果。
我将展示所有需要的函数:
函数 | 参数与功能简介 |
---|---|
push_front | 参数: const value_type& val 功能: 在链表头部插入一个元素的副本。 |
emplace_front | 参数: Args&&... args 功能: 在链表头部直接构造一个元素,无需创建临时对象,通常比 push_front 更高效。 |
push_back | 参数: const value_type& val 功能: 在链表尾部插入一个元素的副本。 |
emplace_back | 参数: Args&&... args 功能: 在链表尾部直接构造一个元素,无需创建临时对象,通常比 push_back 更高效。 |
insert | 参数(单元素): iterator position, const value_type& val 功能: 在指定迭代器 position 之前插入一个元素的副本。参数(多个元素): iterator position, size_type n, const value_type& val 功能: 在 position 之前插入 n 个 val 的副本。参数(迭代器范围): iterator position, InputIterator first, InputIterator last 功能: 在 position 之前插入来自范围 [first, last) 的元素副本。 |
emplace | 参数: iterator position, Args&&... args 功能: 在指定迭代器 position 之前直接构造一个单个元素。这是 insert 单元素插入的高效版本。 |
splice | 参数(整个链表): iterator position, list& l 功能: 将链表 l 的全部元素移动到当前链表的 position 之前。操作后 l 为空。参数(单个元素): iterator position, list& l, iterator i 功能: 将链表 l 中由迭代器 i 指向的单个元素移动到当前链表的 position 之前。参数(元素范围): iterator position, list& l, iterator first, iterator last 功能: 将链表 l 中 [first, last) 范围内的元素移动到当前链表的 position 之前。 |
函数理解起来有点抽象,所以我们以代码为主,代码使用过哪些成员函数,我们再回过头来查看表格加深印象。下面我将通过代码的方式向您展示如何为list插入元素:
#include<bits/stdc++.h> #include<list> /* 如何为list容器添加元素 */ using namespace std; /*通过push_back()、push_front()、emplace_back()、emplace_front()为list添加单个元素*/ void test1() { /*只能添加单个元素*/ list<int> l{1,2,3,4,5};//初始化链表 l.push_back(0) ;//尾增法 cout << "push_back()在l容器尾部添加0后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout<<'\n' ; l.push_front(0) ;//头增法 cout << "push_front()在l容器首部添加0后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout << '\n'; l.emplace_back(0) ;//尾增法 cout << "push_emplace()在l容器尾部添加0后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout<<'\n' ; l.push_front(0) ;//头增法 cout << "emplace_front()在l容器首部添加0后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout << '\n'; cout << '\n'; } /*通过insert()、empplace()为list添加单个或多个元素*/ void test2() { list<int> l{1,2,3,4,5}; /*insert()*/ auto pos3= l.begin() ; for(int i=0;i<2;++i)++pos3;//第三个元素位置迭代器 l.insert(pos3,0) ;//单个添加 cout << "insert()在第三个元素前添加0后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout<<'\n' ; pos3= l.begin() ; for(int i=0;i<2;++i)++pos3;//第三个元素位置迭代器 l.insert(pos3,{9,9,9}) ;//多个添加 cout << "insert()在第三个元素前添加{9,9,9}后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout << '\n'; pos3= l.begin() ; for(int i=0;i<2;++i)++pos3;//第三个元素位置迭代器 l.insert(pos3,3,7) ;//n个体的方式添加 cout << "insert()在第三个元素前添加3个7后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout << '\n'; l.clear();//清空元素,重新测试emplace /*emplace()且只能添加单个元素*/ l={1,2,3,4,5};//'='重载实现直接赋值 pos3= l.begin() ; for(int i=0;i<2;++i)++pos3;//第三个元素位置迭代器 l.insert(pos3,0) ;//只能添加单个元素 cout << "emplace()在第三个元素前添加0后输出所有元素: "; for(auto it = l.begin();it!=l.end();++it)cout << *it << " "; cout << '\n'; cout << '\n'; } /*通过splice()为list拼接链表*/ void test3() { /*准备3个链表*/ list<int> l1{1,2,3} ; list<int> l2{1,2,3} ; list<int> l3{1,2,3} ; /*准备3个消耗链表*/ list<int> t1{1,2,3} ; list<int> t2{1,2,3} ; list<int> t3{1,2,3} ; /*1.splice(iterator pos, list& l)*/ l1.splice(++l1.begin(),t1) ; cout << "链表t1插入到l1的第二个元素之前: "; for(auto it = l1.begin();it!=l1.end();++it)cout << *it << " "; cout << '\n'; /*2.splice(iterator pos, list& l, iterator i)*/ l1.splice(++l2.begin(),t2,++t2.begin()) ; cout << "链表t2的第二个元素插入到l2的第二个元素之前: "; for(auto it = l2.begin();it!=l2.end();++it)cout << *it << " "; cout << '\n'; /*3.splice(iterator pos, list& l, iterator first, iterator last)*/ l1.splice(++l3.begin(),t3,++t3.begin(),t3.end()) ; cout << "链表t3区间[first,last)内所有元素插入到l3的第二个元素之前: "; for(auto it = l3.begin();it!=l3.end();++it)cout << *it << " "; cout << '\n'; } int main(){ test1(); test2(); test3(); return 0; }
虽然比起之前序列式容器学习增加了个splice()拼接,但不影响我们归纳学习list容器。可以看到对list的元素插入也是完全没问题:
学习为list容器添加元素,贵在练习,所谓“熟能生巧”,读者也快试试通过不同成员函数为链表添加元素吧!
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程