2026/4/21 22:32:03
网站建设
项目流程
如何做网站公众号推广,上海品牌女装排行榜前十名,wordpress 全部函数,非常强大的wordpress主题目录一、底层#xff1a;双向链表二、特性#xff1a;优势和局限1. 核心优势2. 局限性三、操作#xff1a;基础运用1. 初始化与赋值2. 插入与删除3. 遍历与访问4. 其他常用接口四、适用场景1. 优先使用list的场景2. 优先使用其他容器的场景五、注意事项1. 迭代器失效2. 排序…目录一、底层双向链表二、特性优势和局限1. 核心优势2. 局限性三、操作基础运用1. 初始化与赋值2. 插入与删除3. 遍历与访问4. 其他常用接口四、适用场景1. 优先使用list的场景2. 优先使用其他容器的场景五、注意事项1. 迭代器失效2. 排序与算法适配3. 遍历效率优化六、总结前言在C STL的容器家族中list是一款基于双向链表实现的序列式容器今天通过本文带大家全面认识STL list助力在实际开发中精准选型、高效使用。一、底层双向链表STL list的底层是双向循环链表每个节点node包含三个核心部分数据域存储实际的数据元素T value前驱指针指向当前节点的前一个节点prev后继指针指向当前节点的后一个节点next。与vector的动态数组不同list的节点在内存中非连续存储节点间通过指针关联形成链表结构。这种设计带来了两个关键特性插入、删除操作无需移动大量元素仅需调整指针指向无法支持随机访问访问元素必须从链表头部或尾部开始遍历。此外STL list通常会维护一个“哨兵节点”用于简化链表的空状态处理和首尾操作逻辑。哨兵节点不存储有效数据其prev指向链表尾节点next指向链表头节点使整个链表形成闭环避免了对空指针的频繁判断。二、特性优势和局限1. 核心优势高效的插入/删除操作在链表任意位置插入或删除元素时间复杂度为O(1)。仅需修改目标节点前后节点的指针无需移动其他元素这是list最突出的优势。稳定的迭代器特性插入、删除操作不会导致除被删除节点外的其他迭代器失效。因为迭代器本质是指向节点的指针只要节点未被删除其地址不变迭代器就依然有效。灵活的内存管理节点按需分配和释放内存无需预先分配连续空间适合存储大量动态增减的元素避免了vector扩容时的内存浪费和拷贝开销。双向遍历支持支持从头部begin()和尾部rbegin()双向遍历满足复杂场景下的遍历需求。2. 局限性不支持随机访问无法通过下标[]或at()方法直接访问指定位置元素访问第n个元素必须从首尾遍历时间复杂度为O(n)效率远低于vector。额外的空间开销每个元素除了存储数据还需额外存储两个指针prev和next对于存储小型数据如int、char的场景空间利用率低于连续存储容器。缓存命中率低由于节点在内存中分散存储无法充分利用CPU缓存的局部性原理遍历效率低于连续内存的容器。三、操作基础运用1. 初始化与赋值#includelist#includeiostreamusingnamespacestd;intmain(){// 1. 空构造listintlst1;// 2. 构造n个值为val的元素listintlst2(5,10);// [10,10,10,10,10]// 3. 迭代器范围构造vectorintvec{1,2,3,4};listintlst3(vec.begin(),vec.end());// [1,2,3,4]// 4. 拷贝构造listintlst4(lst3);// [1,2,3,4]// 5. 赋值操作listintlst5;lst5lst4;// [1,2,3,4]return0;}2. 插入与删除list提供了丰富的插入和删除接口覆盖头部、尾部、任意位置的操作listintlst{1,2,3,4};autoitlst.begin();advance(it,2);// 移动迭代器到第3个元素值为3// 插入操作lst.push_front(0);// 头部插入[0,1,2,3,4]lst.push_back(5);// 尾部插入[0,1,2,3,4,5]lst.insert(it,9);// 迭代器位置插入[0,1,2,9,3,4,5]// 删除操作lst.pop_front();// 头部删除[1,2,9,3,4,5]lst.pop_back();// 尾部删除[1,2,9,3,4]lst.erase(it);// 迭代器位置删除此时it指向3[1,2,9,4]// 批量删除lst.remove(2);// 删除所有值为2的元素[1,9,4]lst.clear();// 清空链表size变为0注意erase(it)会返回指向被删除节点下一个节点的迭代器避免迭代器失效而remove(val)会遍历整个链表删除所有匹配值的节点时间复杂度为O(n)。3. 遍历与访问由于不支持随机访问list的遍历主要依赖迭代器或范围for循环listintlst{1,2,3,4,5};// 1. 正向迭代器遍历for(autoitlst.begin();it!lst.end();it){cout*it ;// 输出1 2 3 4 5}// 2. 反向迭代器遍历for(autoitlst.rbegin();it!lst.rend();it){cout*it ;// 输出5 4 3 2 1}// 3. 范围for循环C11及以上for(intval:lst){coutval ;// 输出1 2 3 4 5}// 4. 访问首尾元素无at()和[]方法coutlst.front();// 1coutlst.back();// 54. 其他常用接口size()返回当前元素个数empty()判断链表是否为空reverse()反转链表时间复杂度O(n)sort()链表内部排序非标准库通用sort因通用sort需随机访问迭代器时间复杂度O(n log n)unique()删除连续重复的元素需先排序时间复杂度O(n)splice()合并两个链表无需拷贝元素仅调整指针时间复杂度O(1)按位置合并或O(n)按范围合并。listintlst1{3,1,4,2};listintlst2{5,6};lst1.sort();// 排序[1,2,3,4]lst1.unique();// 无连续重复保持不变lst1.reverse();// 反转[4,3,2,1]// 把lst2的所有元素插入到lst1头部lst1.splice(lst1.begin(),lst2);// lst1: [5,6,4,3,2,1], lst2: 空四、适用场景list的特性决定了它并非“万能容器”需根据实际场景选型1. 优先使用list的场景频繁在任意位置插入、删除元素尤其是中间位置且元素个数动态变化较大需要保证迭代器稳定性插入/删除后无需重新获取迭代器无需随机访问元素仅需双向遍历需要高效合并两个链表splice接口优势。2. 优先使用其他容器的场景需要随机访问元素如下标访问优先选择vector、array元素个数固定或变化不大且以遍历、读取为主优先选择vector。需要在尾部高效插入/删除且支持随机访问vector尾部操作O(1)存储小型数据如int追求空间利用率vector无指针额外开销。五、注意事项1. 迭代器失效list的迭代器仅在对应节点被删除时失效其他情况插入、移动均有效。因此在遍历删除时需注意保存下一个迭代器// 错误写法erase后it失效it会出错for(autoitlst.begin();it!lst.end();it){if(*it%20){lst.erase(it);// it失效}}// 正确写法利用erase返回的迭代器for(autoitlst.begin();it!lst.end();){if(*it%20){itlst.erase(it);// 接收下一个有效迭代器}else{it;}}2. 排序与算法适配标准库的std::sort要求迭代器支持随机访问而list的迭代器是双向迭代器不满足要求因此必须使用list自带的sort()成员函数不可直接调用std::sort(lst.begin(), lst.end())。3. 遍历效率优化由于list的节点分散遍历效率低于vector。若需频繁遍历且元素个数不频繁变化可考虑将list转为vector后遍历一次性拷贝开销可抵消多次遍历的低效。六、总结STL list是一款针对性极强的容器其核心价值在于高效的任意位置插入/删除操作和稳定的迭代器特性同时也因双向链表的底层结构存在随机访问能力缺失、缓存命中率低等局限。合理的进行选型才能充分发挥STL容器的性能优势。