前面我们已经充分了解deque的基本知识以及访问方式,本节将一口气为读者详细介绍如何对deque进行增删操作,加快我们的学习进度。这里可以类比vector的增删操作,《vector容器怎么在指定位置前插入元素?》、《vector容器怎么删除元素呢?》,读者通过对比学习,总结归纳出自己的宝贵经验,提高对STL容器的掌控力。
我们先谈谈“增”这个操作:
对比vector,我们都知道deque能够实现头增尾增push_front()、push_back();C++11后,deque还能通过emplace_front()、emplace_back()进行头增尾增。相比于前者,后者是直接在内存上构造,省去了相比前者的移动函数、拷贝函数、析构函数这些冗杂过程,提高了元素添加效率。当然,我们也可以指定位置添加元素,如insert()、emplace(),通过位置迭代器添加元素,值得注意的是除insert()外其他添加函数都只能添加一个元素。类比vector的push_back()和emplace_back(),deque对于指定位置添加元素来说,emplace是直接构造,效率高于insert()。那我们通过代码来学习如何为deque增加元素:
#include<bits/stdc++.h> #include<deque> /* 如何为deque容器添加元素 */ using namespace std; /*通过push_back()、push_front()、emplace_back()、emplace_front()为deque添加单个元素*/ void test1() { /*只能添加单个元素*/ deque<int> dq{1,2,3,4,5}; dq.push_back(0) ;//尾增法 cout << "push_back()在dq容器尾部添加0后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout<<'\n' ; dq.push_front(0) ;//头增法 cout << "push_front()在dq容器首部添加0后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout << '\n'; dq.emplace_back(0) ;//尾增法 cout << "push_emplace()在dq容器尾部添加0后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout<<'\n' ; dq.push_front(0) ;//头增法 cout << "emplace_front()在dq容器首部添加0后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout << '\n'; cout << '\n'; } /*通过insert()、empplace()为deque添加单个或多个元素*/ void test2() { deque<int> dq{1,2,3,4,5}; /*insert()*/ dq.insert(dq.begin()+2,0) ;//单个添加 cout << "insert()在第三个元素前添加0后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout<<'\n' ; dq.insert(dq.begin()+2,{9,9,9}) ;//多个添加 cout << "insert()在第三个元素前添加{9,9,9}后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout << '\n'; dq.insert(dq.begin()+2,3,7) ;//n个体的方式添加 cout << "insert()在第三个元素前添加3个7后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout << '\n'; dq.clear();//清空元素,重新测试emplace /*emplace()且只能添加单个元素*/ dq={1,2,3,4,5};//'='重载实现直接赋值 dq.insert(dq.begin()+2,0) ;//只能添加单个元素 cout << "emplace()在第三个元素前添加0后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout << '\n'; } int main(){ test1(); test2(); return 0; }
编译后结果为:
通过代码我们知道,头增尾增只能添加单个元素;指定位置添加元素时,insert()可多个添加,emplace()只能单个添加。
我们再谈谈“减”这个操作:
对比vector,我们都知道deque能够实现头删尾删pop_front()、pop_back();指定位置删除元素erase(),清空容器是clear()。这里重点讲解erase()。对于erase() 来说,参数如果是一个位置迭代器,则删除该位置元素;如果是两个位置迭代器,则删除该区间位置。
话不多说,上代码:
#include<bits/stdc++.h> #include<deque> /* 如何为deque容器删除元素 */ using namespace std; /*重点讲解:通过erase()为deque删除元素*/ void test1() { /*erase()*/ deque<int> dq{1,2,3,4,5,7,8,9,10}; dq.erase(dq.begin()+2) ;//参数为1个位置迭代器,删除第3个元素 cout << "erase(dq.begin()+2)在dq容器内删除第3个元素后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout<<'\n' ; dq.erase(dq.begin()+4,dq.begin()+6) ;//参数为两个迭代器,删除该区间[ begin()+4,begin()+6)所有元素 cout << "erase(begin()+4,begin()+6)在dq容器内删除该区间[ 5,7)所有元素后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout << '\n'; cout << '\n'; } /*练习头删尾删和clear()全清空*/ void test2() { deque<int> dq{1,2,3,4,5}; /*pop首尾元素*/ dq.pop_front() ;//头删 cout << "pop_front()删除第一个元素后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout<<'\n' ; dq.pop_back() ;//尾删 cout << "pop_back()删除最后一个元素后输出所有元素: "; for(int i=0;i<dq.size();++i) cout << dq[i]<<" "; cout<<'\n' ; /*clear()一键清空*/ dq.clear() ; cout << "clear()后dq.size()为:"<< dq.size()<<'\n'; cout<<'\n' ; } int main(){ test1(); test2(); return 0; }
结果也是不出所料,都能按我们的指令实现元素删除:
你以为这就结束了?我这里有一个erase的妙用。大家都知道remove()吧,remove(pos1,pos2,T)里前面两个参数都是位置迭代器,第三个参数T是一个容器内元素,该函数的核心是在覆盖掉区间里的所有T,然后返回该区间内第一个无效内存的位置迭代器。
比如我们有这样一个deque:
{1,2,3,4,5}
如果我们调用remove(dq.begin(),dq.end(),3),容器内会发生这样一个情况:
{1,2,4,5,5}
没错,3被覆盖了,此时remove函数返回迭代器dq.begin()+3,也就是倒数第二个5的位置,此时配合dq.erase(|remove(dq.begin(),dq.end(),3),|dq.end())就能清空dq容器里所有的3了(这里'|'是为了方便观察函数参数)。
问题来了,想要删除deque容器{1,2,3,4,3,5,3,6,3,7}里所有的3,你会怎么做?
#include<bits/stdc++.h> #include<deque> /* 删除deque容器{1,2,3,4,3,5,3,6,3,7}里所有的3 */ using namespace std; void test() { /*erase()+remove()*/ deque<int> dq{1,2,3,4,3,5,3,6,3,7}; dq.erase(remove(dq.begin(),dq.end(),3),dq.end()); cout <<"删除deque容器{1,2,3,4,3,5,3,6,3,7}里所有的3后遍历容器: " ; for(int i=0;i<dq.size();++i) cout << dq[i] << " "; } int main(){ test(); return 0; }
结果为:
也是完成指定元素全清工作,这个remove()+erase()小技巧,你回了吗?
总结:本节详细讲解了deque的增删操作,内容量大管饱,希望对您的提升有帮助。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程