当前位置: 首页 > news >正文

STL算法库讲解1

1. 迭代算法:for_each

核心特性

  • 最基础的遍历算法,对区间[first, last)中的每个元素执行指定操作
  • 非修改性算法(除非操作函数显式修改元素)
  • 支持自定义操作(函数指针、函数对象、Lambda 表达式)
  • 返回值:C++11 后返回传入的操作函数对象

函数原型

template<class InputIt, class UnaryFunction> UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 1. 普通函数作为操作 auto print = [](int x) { std::cout << x << " "; }; std::for_each(vec.begin(), vec.end(), print); // 输出:1 2 3 4 5 std::cout << std::endl; // 2. 修改元素(通过引用捕获) std::for_each(vec.begin(), vec.end(), [](int& x) { x *= 2; }); // 现在vec:{2, 4, 6, 8, 10} // 3. 捕获外部变量 int sum = 0; std::for_each(vec.begin(), vec.end(), [&sum](int x) { sum += x; }); std::cout << "总和:" << sum << std::endl; // 输出:30 return 0; }

注意事项

  • 与 C++11 范围 for 循环的区别:for_each可以返回操作函数对象,适合需要累积状态的场景
  • 操作函数的参数如果是值传递,无法修改原元素;必须使用引用传递int& x
  • 时间复杂度:O (n),遍历一次区间

2. 查找算法

核心特性

  • 在区间中查找单个元素满足条件的元素
  • 返回值:找到则返回指向该元素的迭代器;未找到则返回last迭代器
  • 适用于无序区间(有序区间优先使用二分查找,效率更高)

常用函数

函数功能
find(first, last, value)查找第一个等于value的元素
find_if(first, last, pred)查找第一个满足谓词pred的元素
find_if_not(first, last, pred)查找第一个不满足谓词pred的元素(C++11)
adjacent_find(first, last)查找第一对相邻且相等的元素
find_first_of(first1, last1, first2, last2)查找区间 1 中第一个出现在区间 2 中的元素

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 3, 5, 3, 7, 9, 3}; // 1. 查找指定值 auto it1 = std::find(vec.begin(), vec.end(), 3); if (it1 != vec.end()) { std::cout << "找到3,位置:" << it1 - vec.begin() << std::endl; // 输出:1 } // 2. 查找第一个大于5的元素 auto it2 = std::find_if(vec.begin(), vec.end(), [](int x) { return x > 5; }); std::cout << "第一个大于5的元素:" << *it2 << std::endl; // 输出:7 // 3. 查找第一对相邻相等的元素 std::vector<int> vec2 = {1, 2, 2, 3, 3, 3}; auto it3 = std::adjacent_find(vec2.begin(), vec2.end()); std::cout << "第一对相邻相等的元素:" << *it3 << std::endl; // 输出:2 return 0; }

3. 搜索算法

核心特性

  • 在区间中查找子序列连续重复元素
  • 与查找算法的区别:查找单个元素 vs 查找多个元素组成的序列
  • 返回值:找到则返回子序列起始位置的迭代器;未找到则返回last

常用函数

函数功能
search(first1, last1, first2, last2)查找区间 1 中第一个出现的区间 2 子序列
find_end(first1, last1, first2, last2)查找区间 1 中最后一个出现的区间 2 子序列
search_n(first, last, count, value)查找连续count个等于value的元素

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> text = {1, 2, 3, 4, 2, 3, 4, 5}; std::vector<int> pattern = {2, 3, 4}; // 1. 查找第一个子序列 auto it1 = std::search(text.begin(), text.end(), pattern.begin(), pattern.end()); if (it1 != text.end()) { std::cout << "第一个子序列起始位置:" << it1 - text.begin() << std::endl; // 输出:1 } // 2. 查找最后一个子序列 auto it2 = std::find_end(text.begin(), text.end(), pattern.begin(), pattern.end()); std::cout << "最后一个子序列起始位置:" << it2 - text.begin() << std::endl; // 输出:4 // 3. 查找连续3个5 std::vector<int> vec = {1, 5, 5, 5, 2, 5}; auto it3 = std::search_n(vec.begin(), vec.end(), 3, 5); if (it3 != vec.end()) { std::cout << "找到连续3个5,起始位置:" << it3 - vec.begin() << std::endl; // 输出:1 } return 0; }

4. 统计算法

核心特性

  • 统计区间中满足条件的元素个数或进行数值累积
  • 分为两类:计数类(<algorithm>)和数值累积类(<numeric>

常用函数

头文件函数功能
<algorithm>count(first, last, value)统计等于value的元素个数
<algorithm>count_if(first, last, pred)统计满足谓词pred的元素个数
<numeric>accumulate(first, last, init)计算区间元素与初始值init的和
<numeric>accumulate(first, last, init, op)使用自定义操作op进行累积

用法示例

#include <iostream> #include <vector> #include <algorithm> #include <numeric> int main() { std::vector<int> vec = {1, 2, 3, 4, 5, 3, 3}; // 1. 统计等于3的元素个数 int cnt1 = std::count(vec.begin(), vec.end(), 3); std::cout << "3的个数:" << cnt1 << std::endl; // 输出:3 // 2. 统计偶数个数 int cnt2 = std::count_if(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; }); std::cout << "偶数个数:" << cnt2 << std::endl; // 输出:2 // 3. 计算总和 int sum = std::accumulate(vec.begin(), vec.end(), 0); std::cout << "总和:" << sum << std::endl; // 输出:21 // 4. 计算乘积 int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>()); std::cout << "乘积:" << product << std::endl; // 输出:540 return 0; }

5. 复制或变换算法

核心特性

  • 将源区间的元素复制变换后复制到目标区间
  • 要求目标区间有足够的空间,否则使用back_inserter等插入迭代器
  • 变换算法可以对每个元素执行自定义操作

常用函数

函数功能
copy(first, last, d_first)将区间[first, last)复制到以d_first开头的目标区间
copy_if(first, last, d_first, pred)只复制满足谓词pred的元素(C++11)
copy_n(first, n, d_first)复制前n个元素(C++11)
transform(first, last, d_first, unary_op)对每个元素执行一元操作unary_op后复制
transform(first1, last1, first2, d_first, binary_op)对两个区间的元素执行二元操作后复制

用法示例

#include <iostream> #include <vector> #include <algorithm> #include <iterator> // 用于back_inserter int main() { std::vector<int> src = {1, 2, 3, 4, 5}; std::vector<int> dest; // 1. 复制所有元素(使用back_inserter自动扩容) std::copy(src.begin(), src.end(), std::back_inserter(dest)); // dest:{1, 2, 3, 4, 5} // 2. 复制偶数元素 std::vector<int> even; std::copy_if(src.begin(), src.end(), std::back_inserter(even), [](int x) { return x % 2 == 0; }); // even:{2, 4} // 3. 元素平方变换 std::vector<int> squared; std::transform(src.begin(), src.end(), std::back_inserter(squared), [](int x) { return x * x; }); // squared:{1, 4, 9, 16, 25} // 4. 两个区间元素相加 std::vector<int> a = {1, 2, 3}; std::vector<int> b = {4, 5, 6}; std::vector<int> c; std::transform(a.begin(), a.end(), b.begin(), std::back_inserter(c), std::plus<int>()); // c:{5, 7, 9} return 0; }

6. 填充算法

核心特性

  • 用指定值或生成的值填充区间
  • 分为两类:固定值填充和生成值填充

常用函数

函数功能
fill(first, last, value)value填充区间[first, last)
fill_n(first, n, value)value填充前n个元素
generate(first, last, gen)用生成函数gen的返回值填充区间
generate_n(first, n, gen)用生成函数gen的返回值填充前n个元素

用法示例

#include <iostream> #include <vector> #include <algorithm> #include <random> int main() { std::vector<int> vec(5); // 1. 填充固定值 std::fill(vec.begin(), vec.end(), 10); // vec:{10, 10, 10, 10, 10} // 2. 填充前3个元素为0 std::fill_n(vec.begin(), 3, 0); // vec:{0, 0, 0, 10, 10} // 3. 生成随机数填充 std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(1, 100); std::generate(vec.begin(), vec.end(), [&]() { return dis(gen); }); // 示例输出:{42, 17, 89, 3, 56} return 0; }

7. 删除算法

⚠️ 核心注意事项

STL 删除算法不会真正删除容器元素,只是将需要保留的元素移到区间前部,返回新的尾迭代器。必须配合容器的erase方法才能真正释放内存。

常用函数

函数功能
remove(first, last, value)移除所有等于value的元素
remove_if(first, last, pred)移除所有满足谓词pred的元素
unique(first, last)移除相邻重复的元素(需先排序)
unique(first, last, pred)使用自定义谓词判断重复

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 3, 2, 3, 4, 3, 5}; // 1. 删除所有等于3的元素 auto new_end1 = std::remove(vec.begin(), vec.end(), 3); // 此时vec:{1, 2, 4, 5, ?, ?, ?}(?为未定义值) vec.erase(new_end1, vec.end()); // 真正删除 // vec:{1, 2, 4, 5} // 2. 删除所有偶数 std::vector<int> vec2 = {1, 2, 3, 4, 5, 6}; auto new_end2 = std::remove_if(vec2.begin(), vec2.end(), [](int x) { return x % 2 == 0; }); vec2.erase(new_end2, vec2.end()); // vec2:{1, 3, 5} // 3. 去重(必须先排序) std::vector<int> vec3 = {1, 2, 2, 3, 3, 3, 4}; std::sort(vec3.begin(), vec3.end()); // 先排序 auto new_end3 = std::unique(vec3.begin(), vec3.end()); vec3.erase(new_end3, vec3.end()); // vec3:{1, 2, 3, 4} return 0; }

8. 排序算法

核心特性

  • STL 提供了多种排序算法,适用于不同场景
  • 默认使用<运算符比较,支持自定义比较函数
  • 时间复杂度:O (n log n)(主流排序算法)

常用函数

函数功能时间复杂度稳定性
sort(first, last)对区间进行快速排序(不稳定)O(n log n)不稳定
stable_sort(first, last)对区间进行归并排序(稳定)O(n log n)稳定
partial_sort(first, middle, last)对前middle-first个元素排序O (n log k)(k 为排序元素个数)不稳定
nth_element(first, nth, last)将第 n 个元素放到正确位置,左边都小于它,右边都大于它O(n)不稳定

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {5, 2, 9, 1, 5, 6}; // 1. 默认升序排序 std::sort(vec.begin(), vec.end()); // vec:{1, 2, 5, 5, 6, 9} // 2. 自定义降序排序 std::sort(vec.begin(), vec.end(), std::greater<int>()); // vec:{9, 6, 5, 5, 2, 1} // 3. 部分排序(前3个元素有序) std::vector<int> vec2 = {5, 2, 9, 1, 5, 6}; std::partial_sort(vec2.begin(), vec2.begin() + 3, vec2.end()); // vec2:{1, 2, 5, 9, 5, 6}(前3个最小的元素有序) // 4. 找第3小的元素(索引从0开始) std::vector<int> vec3 = {5, 2, 9, 1, 5, 6}; std::nth_element(vec3.begin(), vec3.begin() + 2, vec3.end()); std::cout << "第3小的元素:" << vec3[2] << std::endl; // 输出:5 return 0; }

9. 堆操作

核心特性

  • STL 实现了大顶堆(默认),即堆顶元素是最大值
  • 堆是一种完全二叉树,存储在数组中
  • 所有堆操作的时间复杂度均为 O (log n)

常用函数

函数功能
make_heap(first, last)将区间[first, last)构建成一个堆
push_heap(first, last)将最后一个元素插入到堆中(需先将元素加到容器末尾)
pop_heap(first, last)将堆顶元素移到区间末尾,剩余元素重新调整为堆
sort_heap(first, last)将堆转换为有序区间(升序)
is_heap(first, last)判断区间是否是一个堆(C++11)

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> heap = {3, 1, 4, 1, 5, 9, 2, 6}; // 1. 构建大顶堆 std::make_heap(heap.begin(), heap.end()); // 堆顶元素是最大值:9 std::cout << "堆顶元素:" << heap.front() << std::endl; // 输出:9 // 2. 插入元素 heap.push_back(7); // 先加到末尾 std::push_heap(heap.begin(), heap.end()); // 调整为堆 // 现在堆顶还是9 // 3. 删除堆顶元素 std::pop_heap(heap.begin(), heap.end()); // 堆顶移到末尾 heap.pop_back(); // 真正删除 // 新堆顶:7 // 4. 堆排序(升序) std::sort_heap(heap.begin(), heap.end()); // heap:{1, 1, 2, 3, 4, 5, 6, 7} return 0; }

10. 二分查找算法

核心特性

  • 要求区间必须是有序的(默认升序)
  • 时间复杂度:O (log n),远快于线性查找的 O (n)
  • 适用于大规模有序数据的查找

常用函数

函数功能返回值
binary_search(first, last, value)判断value是否存在于区间中bool
lower_bound(first, last, value)查找第一个大于等于value的元素迭代器
upper_bound(first, last, value)查找第一个大于value的元素迭代器
equal_range(first, last, value)返回等于value的元素区间pair <迭代器,迭代器>

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 2, 3, 4, 4, 4, 5, 6}; // 1. 判断元素是否存在 bool exists = std::binary_search(vec.begin(), vec.end(), 4); std::cout << "4是否存在:" << std::boolalpha << exists << std::endl; // 输出:true // 2. 查找第一个大于等于4的元素 auto it_low = std::lower_bound(vec.begin(), vec.end(), 4); std::cout << "第一个>=4的元素位置:" << it_low - vec.begin() << std::endl; // 输出:3 // 3. 查找第一个大于4的元素 auto it_high = std::upper_bound(vec.begin(), vec.end(), 4); std::cout << "第一个>4的元素位置:" << it_high - vec.begin() << std::endl; // 输出:6 // 4. 统计等于4的元素个数 int cnt = it_high - it_low; std::cout << "4的个数:" << cnt << std::endl; // 输出:3 return 0; }

11. 交换算法

核心特性

  • 交换两个元素或两个区间的元素
  • 是 STL 中最基础的算法之一,被其他算法广泛调用

常用函数

函数功能
swap(a, b)交换两个对象ab的值
iter_swap(it1, it2)交换两个迭代器it1it2指向的元素
swap_ranges(first1, last1, first2)交换两个区间的元素

用法示例

#include <iostream> #include <vector> #include <algorithm> int main() { // 1. 交换两个变量 int a = 10, b = 20; std::swap(a, b); std::cout << "a=" << a << ", b=" << b << std::endl; // 输出:a=20, b=10 // 2. 交换两个迭代器指向的元素 std::vector<int> vec = {1, 2, 3, 4}; std::iter_swap(vec.begin(), vec.end() - 1); // vec:{4, 2, 3, 1} // 3. 交换两个区间的元素 std::vector<int> vec1 = {1, 2, 3}; std::vector<int> vec2 = {4, 5, 6}; std::swap_ranges(vec1.begin(), vec1.end(), vec2.begin()); // vec1:{4, 5, 6}, vec2:{1, 2, 3} return 0; }
http://www.jsqmd.com/news/955588/

相关文章:

  • Mysql报错:跳至内容辅助功能反馈[ERROR] InnoDB: Operating system error number 13 in a file operation.的解决方法
  • 基于TensorFlow的YOLO目标检测环境搭建与实战部署指南
  • MuleSoft企业级LLM编排实践:安全、可观测、可治理的AI服务化
  • 去离子水选哪家?认识一下西南本土企业贵州巧源水处理 - 深度智识库
  • 2026年洛阳酒店茶桌采购要点:从源头工厂直营到高端茶空间定制的核心选型框架 - 精选优质企业推荐官
  • Waveform数据集KMeans聚类实战包:无噪声基准与20%高斯噪声鲁棒性对比
  • 口碑为王!无锡昱邦安为何成为锂电池充电柜口碑标杆? - 品牌推荐大师
  • FPGA时序分析实战:从TimeQuest波形图到SDC约束的完整指南
  • 3分钟掌握电子课本下载神器:智慧教育平台资源获取终极指南
  • 【Excel提效 No.096】一句话搞定银行卡号提取,自动校验避免错误
  • LED背光电视供应链格局解析:技术壁垒与国产替代机遇
  • Android屏幕适配终极解决方案:深入解析AutoSize框架架构设计与实战应用
  • 2026 南京名表回收 TOP6 排行,深耕本地数十年表行报价更贴合行情 - 薛定谔的梨花猫
  • 2026年阿里企业邮箱如何购买?联系电话及开通流程详解 - 品牌2026
  • 直接用的商务风公众号排版模板推荐:公司工作计划模板 - 一串葡萄
  • OMAP3530异构多核开发环境搭建:从工具链配置到DSP/ARM协同实战
  • 【Java毕设源码分享】基于SpringBoot的智能餐饮管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 不知道怎么选合适的全自动咖啡机,国产专业商用全自动咖啡机值得关注 - 品牌2026
  • 基于手机桥接与4G网络的无人机超视距控制方案设计与实现
  • 从KVM到VMware内核:深入聊聊PVE/unRaid与ESXi在CPU虚拟化性能损耗上的那点事儿
  • 如何利用ExDark数据集解决低光照视觉问题的实战指南
  • 2026年洛阳酒店茶桌采购全攻略:从工厂直营到茶空间美学一站式解决方案 - 精选优质企业推荐官
  • 慕课助手终极指南:如何让你的在线学习效率提升300%
  • 大连出手黄金不用瞎比价,实用变现步骤帮你规避回收各类陷阱 - 奢侈品回收评测
  • 【Java毕设源码分享】基于springboot的共享自行车共享单车管理系统(程序+文档+代码讲解+一条龙定制)
  • 校园志愿者服务全流程管理系统:Spring Boot+Redis签到+多角色权限+时长自动统计
  • MATLAB图像像素级分割工具集:CNN/SAE/DBN等五种网络一键训练与测试
  • 2026年洛阳原木大板选购守则:从源头工厂直营到高端茶空间定制 - 精选优质企业推荐官
  • 深入拆解大模型Token黑洞:为什么 AI Agent 时代我们需要从 FinOps 转向 FinAPI 治理范式?
  • Windows下GTK开发环境配置:从Dev-C++到跨平台GUI编程实战