大足网站建设公司,成都设计咨询集团官网,佛山网约车租赁公司,可以做装修效果图的网站#x1f466;个人主页#xff1a;Weraphael ✍#x1f3fb;作者简介#xff1a;目前学习C和算法 ✈️专栏#xff1a;C航路 #x1f40b; 希望大家多多支持#xff0c;咱一起进步#xff01;#x1f601; 如果文章对你有帮助的话 欢迎 评论#x1f4ac; 点赞#x1… 个人主页Weraphael ✍作者简介目前学习C和算法 ✈️专栏C航路 希望大家多多支持咱一起进步 如果文章对你有帮助的话 欢迎 评论 点赞 收藏 加关注✨ 目录 一、list的基本概念二、list的构造2.1 默认构造2.2 拷贝构造函数2.3 用n个值为val的元素构造2.4 用迭代区间的元素构造 三、list的迭代器begin end四、list的容量操作4.1 size4.2 empty 五、list的遍历5.1 迭代器遍历5.2 范围for 六、list的获取元素操作6.1 front6.2 back七、list的对容器修改操作7.1 push_front7.2 pop_front7.3 push_back7.4 pop_back7.5 insert 迭代器随机访问问题7.6 erase 迭代器失效问题7.7 swap7.8 clear 八、其他操作常见8.1 reverse8.2 sort8.3 remove8.4 unique 九、 list与vector的对比 一、list的基本概念
功能将数据进行链式存储。链表(list)是一种物理存储单元上非连续的存储结构数据元素的逻辑顺序是通过链表中的指针链接实现的。链表的组成:链表由一系列结点组成。结点的组成:一个是存储数据元素的数据域另一个是存储下一个结点地址的指针域。STL中的链表是一个 双向带头循环链表。这意味着链表中的每个节点都包含指向前一个节点和后一个节点的指针而头节点和尾节点互相连接形成一个循环。这样的设计使得在链表中插入、删除节点的操作更加高效同时也提供了双向遍历链表的能力。list的数据域同样可以存储不同数据类型因此它同样是一个模板容器。
二、list的构造
2.1 默认构造
listint l;构造空的list对象 2.2 拷贝构造函数
【函数原型】
list (const list x)【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l1{ 1,2,3,4,5 };cout l1;for (auto x : l1){cout x ;}cout endl;// 拷贝构造函数listint l2(l1);cout l2;for (auto x : l2){cout x ;}cout endl;return 0;
}【输出结果】 2.3 用n个值为val的元素构造
【函数原型】
list (size_type n, const value_type val value_type())没有显示给出第二个参数默认为0
【代码示例】
#include iostream
#include list
using namespace std;int main()
{// 初始化10个alistchar lc(10, a);for (auto x : lc){cout x ;}cout endl;return 0;
}【输出结果】 2.4 用迭代区间的元素构造
【函数原型】
list (InputIterator first, InputIterator last)注意迭代区间的范围通常是左闭右开的[first, last)
【代码示例】
#include iostream
#include list
using namespace std;int main()
{int a[] { 0,1,2,3,4,5,6,7,8,9 };int size sizeof(a) / sizeof(a[0]); // 计算元素个数listint ll(a, a size);for (auto x : ll){cout x ;}cout endl;return 0;
}【输出结果】 三、list的迭代器begin end begin返回第一个元素的迭代器end返回最后一个元素下一个位置的迭代器 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l4{ 1,2,3 };listint::iterator it l4.begin();while (it ! l4.end()){cout *it ;it;}cout endl;return 0;
}【输出结果】 四、list的容量操作
4.1 size 功能返回list中有效节点的个数 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l4{ 1,2,3 };cout 有效节点个数 l4.size() endl;return 0;
}
【输出结果】 4.2 empty 功能检测list是否为空是返回true否则返回false 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l4;if (l4.empty()){cout l4是空结点 endl;}else{cout l4不是空结点 endl;cout l4的有效结点 l4.size() endl;}return 0;
}
【输出结果】 五、list的遍历
list本质是链表不是用连续性空间存储数据的。因此list是不支持下标访问[]
5.1 迭代器遍历
【代码示例】
#include iostream
#include list
using namespace std;int main()
{listchar lc;// 尾插lc.push_back(c);lc.push_back(x);lc.push_back(k);lc.push_back(h);lc.push_back(s);listchar::iterator it lc.begin();while (it ! lc.end()){cout *it ;it;}cout endl;// 以上代码可以结合成for循环的形式// listchar::iterator太长可使用autofor (auto it lc.begin(); it ! lc.end(); it){cout *it ;}cout endl;return 0;
}【输出结果】 5.2 范围for
由于list支持迭代器那么就一定支范围for。因为范围for的底层就是迭代器实现的
【代码实现】
#include iostream
#include list
using namespace std;int main()
{listchar lc;// 尾插lc.push_back(c);lc.push_back(x);lc.push_back(k);lc.push_back(h);lc.push_back(s);for (auto x : lc){cout x ;}cout endl;return 0;
}
【输出结果】 六、list的获取元素操作
6.1 front 功能返回list的第一个节点中值的引用。 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.push_back(5);cout 第一个结点的值 l5.front() endl;return 0;
}【输出结果】 6.2 back 功能返回list的最后一个节点中值的引用。 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.push_back(5);cout 最后一个节点的值 l5.back() endl;return 0;
}【输出结果】 七、list的对容器修改操作
7.1 push_front 功能头插 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.push_back(5);// 头插l5.push_front(100);for (auto x : l5){cout x ;}cout endl;return 0;
}【输出结果】 7.2 pop_front 功能头删 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.push_back(5);l5.pop_front();for (auto x : l5){cout x ;}cout endl;return 0;
}【输出结果】 7.3 push_back 功能尾插 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.push_back(5);for (auto x : l5){cout x ;}cout endl;return 0;
}【输出结果】 7.4 pop_back 功能尾删 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.pop_back();for (auto x : l5){cout x ;}cout endl;return 0;
}【输出结果】 7.5 insert 迭代器随机访问问题
从vector开始insert都是使用迭代器来访问的 假设已有数据1 2 3 4现要在2后插入100。根据以往所学知识不难可以写出以下代码
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);l5.insert(l5.begin() 2, 100);for (auto x : l5){cout x ;}cout endl;return 0;
}【输出结果】 可惜报错了。
原因是list本质是链表不是用连续性空间存储数据的迭代器也是不支持随机访问的只能支持和--操作支持双向遍历
那可能就有人想的底层就是1那么为什么1不行而可以
这都归功于类的封装在对迭代器封装的时候重新的定义了这些符号的意义也就是符号的重载。这才使得我们能就像使用指针一样去使用迭代器。下面是list的源代码部分 self operator() { node (link_type)((*node).next);return *this;}self operator(int) { self tmp *this;*this;return tmp;}
self operator--() { node (link_type)((*node).prev);return *this;
}
self operator--(int)
{ self tmp *this;--*this;return tmp;
}【正确写法】
#include iostream
#include list
using namespace std;int main()
{listint l5;l5.push_back(1);l5.push_back(2);l5.push_back(3);l5.push_back(4);auto it l5.begin();for (int i 0; i 2; i){it;}l5.insert(it, 100);for (auto x : l5){cout x ;}cout endl;return 0;
}【输出结果】 接下来我们想对于insertlist会和vector一样有迭代器失效的问题吗
答案是没有。原因是vector在插入时如果遇到扩容才会存在迭代器失效而list不存在扩容。
7.6 erase 迭代器失效问题 功能删除list position位置的元素 【代码示例】
目的删除所有元素
#include iostream
#include list
using namespace std;int main()
{int a[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };listint l(a, a sizeof(a) / sizeof(a[0]));cout 删除前;for (auto x : l){cout x ;}cout endl;auto it l.begin();while (it ! l.end()){l.erase(it);it;}cout 删除后;for (auto x : l){cout x ;}cout endl;return 0;
}【输出结果】 程序崩了
这和vector的情况类似erase()函数执行后it所指向的节点已被删除因此it无效。
解决方法在下一次使用it时必须先给其赋值
【正确代码】
#include iostream
#include list
using namespace std;int main()
{int a[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };listint l(a, a sizeof(a) / sizeof(a[0]));cout 删除前;for (auto x : l){cout x ;}cout endl;auto it l.begin();while (it ! l.end()){// l.erase(it); 错误it l.erase(it);}cout 删除后;for (auto x : l){cout x ;}cout endl;return 0;
}【输出结果】 7.7 swap 功能交换两个list中的元素 #include iostream
#include list
using namespace std;int main()
{listint l1;l1.push_back(1);l1.push_back(1);l1.push_back(1);l1.push_back(1);listint l2;l2.push_back(2);l2.push_back(2);l2.push_back(2);l2.push_back(2);cout 交换前 endl;cout l1;for (auto x : l1){cout x ;}cout endl;cout l2;for (auto x : l2){cout x ;}cout endl;l1.swap(l2);cout 交换后 endl;cout l1;for (auto x : l1){cout x ;}cout endl;cout l2;for (auto x : l2){cout x ;}cout endl;return 0;
}【输出结果】 7.8 clear 功能清空list中所有的有效元素 #include iostream
#include list
using namespace std;int main()
{listint l1;l1.push_back(1);l1.push_back(1);l1.push_back(1);l1.push_back(1);l1.clear();if (l1.empty()){cout 已清空 endl;}return 0;
}【输出结果】 八、其他操作常见 主要讲解画方括号的剩下的自行了解即可~
8.1 reverse 功能逆置list 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listchar lc1;lc1.push_back(a);lc1.push_back(b);lc1.push_back(c);lc1.push_back(d);// list的逆置接口lc1.reverse();for (auto x : lc1){cout x ;}cout endl;return 0;
}【输出结果】 其实list设计这个接口没有必要因为算法库algorithm也设计了reverse算法 【代码示例】
#include iostream
#include list
#include algorithm // 使用算法库需要包含头文件
using namespace std;int main()
{listchar lc1;lc1.push_back(a);lc1.push_back(b);lc1.push_back(c);lc1.push_back(d);// 算法库逆置reverse(lc1.begin(), lc1.end());for (auto x : lc1){cout x ;}cout endl;return 0;
}【输出结果】 8.2 sort 功能排序list。注意list底层的sort是归并算法 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint ll;ll.push_back(5);ll.push_back(4);ll.push_back(1);ll.push_back(2);ll.push_back(6);ll.push_back(3);ll.sort();for (auto x : ll){cout x ;}cout endl;return 0;
}但是算法库里面也设计了一个sort但注意算法库里面的sort对于list是用不了的。 首先从模板参数上就能发现名字有所不同
事实上这是因为迭代器从功能上进行了分类。
InputIterator就是所有迭代器都可以用。 bidirectional这种迭代器就适合双向的迭代器用。 RadomAccessIterator就适合随机迭代器去使用。
因此由于list适合双向迭代器所以用不了库里的sort(RadomAccessIterator)
那我们怎么知道一个容器是什么类型的迭代器呢很简单查文档就行点击跳转
这里我为大家总结了一些常见容器的迭代器 因此list接口中实现sort还是有点意义的。我只是说“有点”。
在排序中vector的排序速度要比list快。这是因为vector是一个连续存储的容器它的元素在内存中是相邻的可以利用局部性原理进行高效的排序算法如快速排序。
相比之下list是一个链表结构其元素在内存中是分散存储的无法直接利用局部性原理因此排序操作的性能通常较慢。
在某些特定情况下list可能更适合进行插入和删除操作因为它对于这些操作的开销较小。因此在选择容器时应该根据具体的需求来决定使用哪种容器。
8.3 remove 功能删除list某个有效数据 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint lit;lit.push_back(1);lit.push_back(2);lit.push_back(3);lit.push_back(4);for (auto x : lit){cout x ;}cout endl;// 删除4lit.remove(4);for (auto x : lit){cout x ;}cout endl;return 0;
}【输出结果】 8.4 unique 功能去重。但是要注意首先得先进行排序才能进行去重。否则效率极低 【代码示例】
#include iostream
#include list
using namespace std;int main()
{listint lit;lit.push_back(3);lit.push_back(4);lit.push_back(1);lit.push_back(2);lit.push_back(4);for (auto x : lit){cout x ;}cout endl;// 去重lit.sort();lit.unique();for (auto x : lit){cout x ;}cout endl;return 0;
}【输出结果】 九、 list与vector的对比
vectolist底层结构动态顺序表一段连续的空间带头结点的双向循环链表随机访问支持随机访问访问某个元素效率O(1)不支持随机访问访问某个元素插入和删除任意位置插入和删除效率低需要搬移元素时间复杂度为O(N)插入时有可能需要增容增容开辟新空间拷贝元素释放旧空间导致效率更低任意位置插入和删除效率高不需要搬移元素时间复杂度为O(1)空间利用率底层为连续空间不容易造成内存碎片空间利用率高缓存利用率高底层节点动态开辟小节点容易造成内存碎片空间利用率低缓存利用率低迭代器原生态指针对原生态指针(节点指针)进行封装迭代器失效问题在插入元素时要给所有的迭代器重新赋值因为插入元素有可能会导致重新扩容致使原来迭代器失效删时当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效删除元素时只会导致当前迭代器失效其他迭代器不受影响使用场景需要高效存储支持随机访问不关心插入删除效率大量插入和删除操作不关心随机访问 文章转载自: http://www.morning.xqgfy.cn.gov.cn.xqgfy.cn http://www.morning.hkysq.cn.gov.cn.hkysq.cn http://www.morning.lhztj.cn.gov.cn.lhztj.cn http://www.morning.ghlyy.cn.gov.cn.ghlyy.cn http://www.morning.dmsxd.cn.gov.cn.dmsxd.cn http://www.morning.lmzpk.cn.gov.cn.lmzpk.cn http://www.morning.znqxt.cn.gov.cn.znqxt.cn http://www.morning.ptwqf.cn.gov.cn.ptwqf.cn http://www.morning.thxfn.cn.gov.cn.thxfn.cn http://www.morning.yntsr.cn.gov.cn.yntsr.cn http://www.morning.tgbx.cn.gov.cn.tgbx.cn http://www.morning.xknmn.cn.gov.cn.xknmn.cn http://www.morning.knczz.cn.gov.cn.knczz.cn http://www.morning.xkmrr.cn.gov.cn.xkmrr.cn http://www.morning.ghxtk.cn.gov.cn.ghxtk.cn http://www.morning.ltcnd.cn.gov.cn.ltcnd.cn http://www.morning.nzqqd.cn.gov.cn.nzqqd.cn http://www.morning.mxlwl.cn.gov.cn.mxlwl.cn http://www.morning.cjwkf.cn.gov.cn.cjwkf.cn http://www.morning.srjbs.cn.gov.cn.srjbs.cn http://www.morning.ndyrb.com.gov.cn.ndyrb.com http://www.morning.fglxh.cn.gov.cn.fglxh.cn http://www.morning.fqsxf.cn.gov.cn.fqsxf.cn http://www.morning.rlwgn.cn.gov.cn.rlwgn.cn http://www.morning.cczrw.cn.gov.cn.cczrw.cn http://www.morning.qhczg.cn.gov.cn.qhczg.cn http://www.morning.wfjyn.cn.gov.cn.wfjyn.cn http://www.morning.pangucheng.cn.gov.cn.pangucheng.cn http://www.morning.jfwrf.cn.gov.cn.jfwrf.cn http://www.morning.ndpwg.cn.gov.cn.ndpwg.cn http://www.morning.xfwnk.cn.gov.cn.xfwnk.cn http://www.morning.zffps.cn.gov.cn.zffps.cn http://www.morning.hmpxn.cn.gov.cn.hmpxn.cn http://www.morning.gfznl.cn.gov.cn.gfznl.cn http://www.morning.phechi.com.gov.cn.phechi.com http://www.morning.ytrbq.cn.gov.cn.ytrbq.cn http://www.morning.cljmx.cn.gov.cn.cljmx.cn http://www.morning.lzjxn.cn.gov.cn.lzjxn.cn http://www.morning.klltg.cn.gov.cn.klltg.cn http://www.morning.ypjjh.cn.gov.cn.ypjjh.cn http://www.morning.zpqbh.cn.gov.cn.zpqbh.cn http://www.morning.kpcjl.cn.gov.cn.kpcjl.cn http://www.morning.tfpqd.cn.gov.cn.tfpqd.cn http://www.morning.mpngp.cn.gov.cn.mpngp.cn http://www.morning.lpppg.cn.gov.cn.lpppg.cn http://www.morning.ptqds.cn.gov.cn.ptqds.cn http://www.morning.gwqq.cn.gov.cn.gwqq.cn http://www.morning.rqhn.cn.gov.cn.rqhn.cn http://www.morning.rcntx.cn.gov.cn.rcntx.cn http://www.morning.mcjp.cn.gov.cn.mcjp.cn http://www.morning.ppbrq.cn.gov.cn.ppbrq.cn http://www.morning.fwcjy.cn.gov.cn.fwcjy.cn http://www.morning.lkkgq.cn.gov.cn.lkkgq.cn http://www.morning.bpp999.com.gov.cn.bpp999.com http://www.morning.tfsyk.cn.gov.cn.tfsyk.cn http://www.morning.stlgg.cn.gov.cn.stlgg.cn http://www.morning.mcndn.cn.gov.cn.mcndn.cn http://www.morning.mnbgx.cn.gov.cn.mnbgx.cn http://www.morning.snbry.cn.gov.cn.snbry.cn http://www.morning.xkgyh.cn.gov.cn.xkgyh.cn http://www.morning.pnmnl.cn.gov.cn.pnmnl.cn http://www.morning.cszbj.cn.gov.cn.cszbj.cn http://www.morning.hbpjb.cn.gov.cn.hbpjb.cn http://www.morning.zyffq.cn.gov.cn.zyffq.cn http://www.morning.pwksz.cn.gov.cn.pwksz.cn http://www.morning.dyxlj.cn.gov.cn.dyxlj.cn http://www.morning.fmqng.cn.gov.cn.fmqng.cn http://www.morning.nnqrb.cn.gov.cn.nnqrb.cn http://www.morning.rfrnc.cn.gov.cn.rfrnc.cn http://www.morning.nylbb.cn.gov.cn.nylbb.cn http://www.morning.fksrg.cn.gov.cn.fksrg.cn http://www.morning.qypjk.cn.gov.cn.qypjk.cn http://www.morning.njftk.cn.gov.cn.njftk.cn http://www.morning.nmfml.cn.gov.cn.nmfml.cn http://www.morning.pgzgy.cn.gov.cn.pgzgy.cn http://www.morning.skksz.cn.gov.cn.skksz.cn http://www.morning.srkwf.cn.gov.cn.srkwf.cn http://www.morning.qhmql.cn.gov.cn.qhmql.cn http://www.morning.qjtbt.cn.gov.cn.qjtbt.cn http://www.morning.fqhbt.cn.gov.cn.fqhbt.cn