
本文是 C 系列教程的第 11 篇。进阶阶段6-10 篇已完成本篇进入 STL 阶段先总览六大容器家族再深入序列容器 vector扩容机制、deque、list、forward_list、array 的用法与选择。一、STL 总览1.1 什么是 STLSTLStandard Template Library标准模板库是 C 标准库的核心由容器、迭代器、算法、函数对象、适配器五大部分组成。它把「数据存储」与「数据处理」解耦实现高效复用。1.2 六大容器家族类别容器特点序列容器vector, deque, list, forward_list, array线性存储按位置访问关联容器set, multiset, map, multimap红黑树自动排序无序容器unordered_set, unordered_map 等哈希表O(1) 查找容器适配器stack, queue, priority_queue限制接口的包装字符串string字符序列其他bitset, valarray专用1.3 如何选择容器需求推荐容器随机访问 尾部增删vector头尾都频繁增删deque任意位置频繁插入删除list需要有序且唯一set / map需要快速查找unordered_map / unordered_set先进后出stack先进先出queue取最大/最小元素priority_queue二、vector 详解2.1 vector 基本操作#includeiostream#includevectorusingnamespacestd;intmain(){// 创建vectorintv1;// 空vectorintv2(5);// 5 个 0vectorintv3(5,10);// 5 个 10vectorintv4{1,2,3,4};// 列表初始化// 增删v1.push_back(10);// 尾部添加v1.push_back(20);v1.push_back(30);v1.pop_back();// 删除尾部30// 访问coutv1[0] v1[0]endl;// 10coutv1.at(1) v1.at(1)endl;// 20带边界检查coutfront v1.front()endl;// 10coutback v1.back()endl;// 20// 大小coutsize v1.size()endl;// 2coutempty v1.empty()endl;// 0coutcapacity v1.capacity()endl;// 2可能// 遍历for(intx:v1)coutx ;coutendl;return0;}2.2 vector 扩容机制vector 容量不足时按倍增策略扩容通常 ×2元素迁移到新内存#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv;intprevCap0;for(inti0;i16;i){v.push_back(i);if(v.capacity()!prevCap){coutpush_back(i) 后容量: v.capacity()endl;prevCapv.capacity();}}return0;}典型输出容量变化 1→2→4→8→16push_back(0) 后容量: 1 push_back(1) 后容量: 2 push_back(2) 后容量: 4 push_back(4) 后容量: 8 push_back(8) 后容量: 16意义倍增策略让 push_back 的均摊复杂度为 O(1)但扩容时旧迭代器全部失效。2.3 插入与删除#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv{1,2,3,4,5};// insert在指定位置前插入v.insert(v.begin()2,99);// 1 2 99 3 4 5v.insert(v.end(),100);// 尾部插入 push_back// erase删除指定位置v.erase(v.begin());// 删除第一个v.erase(v.begin()1,v.begin()3);// 删除区间for(intx:v)coutx ;coutendl;// clear清空v.clear();coutclear 后 size v.size()endl;return0;}2.4 迭代器失效问题#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv{1,2,3,4,5};// 错误示范erase 后迭代器失效// for (auto it v.begin(); it ! v.end(); it) {// if (*it % 2 0) v.erase(it); // 危险it 失效// }// 正确示范erase 返回下一个有效迭代器for(autoitv.begin();it!v.end();){if(*it%20){itv.erase(it);// 删除并获取下一个}else{it;}}for(intx:v)coutx ;coutendl;// 1 3 5return0;}2.5 实用操作#includeiostream#includevector#includealgorithmusingnamespacestd;intmain(){vectorintv{3,1,4,1,5,9,2,6};// 排序sort(v.begin(),v.end());// 1 1 2 3 4 5 6 9//反转reverse(v.begin(),v.end());// 9 6 5 4 3 2 1 1// 查找autoitfind(v.begin(),v.end(),4);if(it!v.end()){cout找到 4 在位置 (it-v.begin())endl;}// 统计cout1 出现次数: count(v.begin(),v.end(),1)endl;// 最大值最小值cout最大值: *max_element(v.begin(),v.end())endl;cout最小值: *min_element(v.begin(),v.end())endl;// 删除重复先排序再 uniquesort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());for(intx:v)coutx ;coutendl;// 1 2 3 4 5 6 9return0;}三、deque 双端队列3.1 deque 特点dequedouble-ended queue支持头尾双端高效增删随机访问 O(1)#includeiostream#includedequeusingnamespacestd;intmain(){dequeintd{2,3,4};d.push_back(5);// 尾部添加2 3 4 5d.push_front(1);// 头部添加1 2 3 4 5d.pop_back();// 删除尾部1 2 3 4d.pop_front();// 删除头部2 3 4// 随机访问O(1)coutd[1] d[1]endl;// 3for(intx:d)coutx ;coutendl;// 2 3 4return0;}3.2 vector vs deque 对比维度vectordeque头部插入慢O(n)快O(1)尾部插入快O(1)均摊快O(1)随机访问O(1)O(1)内存连续分段连续扩容迁移全部元素不彲响已有元素适用尾部操作为主头尾都要操作四、list 双向链表4.1 list 基本操作list 是双向链表任意位置插入删除 O(1)但不支持随机访问#includeiostream#includelistusingnamespacestd;intmain(){listintlst{3,1,4};// 头尾插入lst.push_back(5);lst.push_front(0);// 0 3 1 4 5// 任意位置插入O(1)autoitlst.begin();advance(it,2);// 移到第 3 个元素lst.insert(it,99);// 0 3 99 1 4 5// 删除lst.remove(99);// 按值删除// 排序与反转list 有自己的成员函数lst.sort();lst.reverse();for(intx:lst)coutx ;coutendl;//54310return0;}4.2 list 特有的高效操作#includeiostream#includelistusingnamespacestd;intmain(){listintl1{1,2,3,4,5};listintl2{10,20,30};// splice把 l2 的元素移到 l1O(1)不拷贝l1.splice(l1.end(),l2);// l1: 1 2 3 4 5 10 20 30, l2: 空// merge合并两个已排序链表listinta{1,3,5};listintb{2,4,6};a.merge(b);// a: 1 2 3 4 5 6// unique去除相邻重复listintc{1,1,2,2,2,3};c.unique();// c: 1 2 3for(intx:a)coutx ;coutendl;return0;}五、forward_list 与 array5.1 forward_list 单向链表#includeiostream#includeforward_listusingnamespacestd;intmain(){// 单向链表只能向前遍历内存更省forward_listintfl{1,2,3};fl.push_front(0);// 0 1 2 3只能头插fl.pop_front();// 1 2 3// 在某个元素后插入insert_afterautoitfl.begin();fl.insert_after(it,99);// 1 99 2 3for(intx:fl)coutx ;coutendl;return0;}5.2 array 固定数组#includeiostream#includearrayusingnamespacestd;intmain(){// 固定大小栈上分配无动态开销arrayint,5arr{1,2,3,4,5};// 与 C 数组兼容coutsize arr.size()endl;// 安全访问coutarr.at(0) arr.at(0)endl;// 迭代器支持for(autoitarr.begin();it!arr.end();it){cout*it ;}coutendl;// 传给 C 风格函数int*cArrarr.data();coutcArr[2] cArr[2]endl;// 3return0;}六、序列容器对比总结容器随机访问头插入尾插入中间插入内存适用vectorO(1)O(n)O(1)*O(n)连续默认首选dequeO(1)O(1)O(1)O(n)分段双端队列listO(n)O(1)O(1)O(1)分散频繁中间操作forward_listO(n)O(1)-O(1)最省极端内存敏感arrayO(1)---栈固定大小*均摊复杂度。七、实战成绩统计系统综合本篇知用 vector 实现成绩统计#includeiostream#includevector#includealgorithm#includenumericusingnamespacestd;classScoreManager{private:vectorintscores;public:voidadd(intscore){scores.push_back(score);}doubleaverage()const{if(scores.empty())return0;returnaccumulate(scores.begin(),scores.end(),0.0)/scores.size();}intmax()const{return*max_element(scores.begin(),scores.end());}intmin()const{return*min_element(scores.begin(),scores.end());}voidsortAndShow()const{vectorinttempscores;// 拷贝排序不改变原数据sort(temp.begin(),temp.end());for(ints:temp)couts ;coutendl;}// 统计及格人数intcountPass(intthreshold60)const{returncount_if(scores.begin(),scores.end(),[threshold](ints){returnsthreshold;});}};intmain(){ScoreManager sm;sm.add(85);sm.add(92);sm.add(58);sm.add(76);sm.add(88);cout平均分: sm.average()endl;// 79.8cout最高分: sm.max()endl;// 92cout最低分: sm.min()endl;// 58cout及格人数: sm.countPass()endl;// 4cout排序后: ;sm.sortAndShow();// 58 76 85 88 92return0;}总结本篇总览了 STL 六大容器家族与选择原则深入讲解了 vector扩容机制、迭代器失效、deque、list、forward_list、array 的特性与适用场景并用成绩统计系统串联实战。重点掌握vector 的扩容与迭代器失效、list 的 splice/merge 高效操作、各容器的选择依据。下一篇将讲解关联容器与无序容器set/map、unordered_*敬请期待