跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 修改序列操作
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C++修改序列操作 = '''修改序列操作'''是C++标准模板库(STL)算法中一组重要的函数,它们能够直接修改容器中的元素或序列。这些操作包括复制、移动、替换、填充、删除等,为开发者提供了高效处理数据序列的工具。 == 概述 == 修改序列操作是指那些能够改变容器中元素内容或顺序的STL算法。与不修改序列的算法(如查找或计数)不同,这些算法会直接对输入序列进行修改。它们通常接受迭代器作为参数,指定要操作的序列范围。 这些算法定义在<algorithm>头文件中,主要包括以下几类操作: * 复制和移动元素 * 替换元素 * 填充序列 * 生成元素 * 删除元素 * 唯一化操作 * 反转和旋转 * 随机重排 == 主要算法及示例 == === 复制操作 === ==== copy ==== 将源序列的元素复制到目标序列。 <syntaxhighlight lang="cpp"> #include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> src = {1, 2, 3, 4, 5}; std::vector<int> dst(5); // 预分配空间 std::copy(src.begin(), src.end(), dst.begin()); for (int i : dst) { std::cout << i << " "; } // 输出: 1 2 3 4 5 } </syntaxhighlight> ==== copy_if ==== 仅复制满足条件的元素。 <syntaxhighlight lang="cpp"> std::vector<int> src = {1, 2, 3, 4, 5}; std::vector<int> dst; std::copy_if(src.begin(), src.end(), std::back_inserter(dst), [](int x){ return x % 2 == 0; }); // dst 包含: 2 4 </syntaxhighlight> === 移动操作 === ==== move ==== 将元素从一个序列移动到另一个序列。 <syntaxhighlight lang="cpp"> std::vector<std::string> src = {"hello", "world"}; std::vector<std::string> dst(2); std::move(src.begin(), src.end(), dst.begin()); // src中的元素现在处于有效但未指定的状态 </syntaxhighlight> === 替换操作 === ==== replace ==== 将序列中所有等于特定值的元素替换为新值。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 2, 3, 2, 1}; std::replace(v.begin(), v.end(), 2, 42); // v 变为: 1, 42, 3, 42, 1 </syntaxhighlight> ==== replace_if ==== 根据谓词条件替换元素。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 2, 3, 4, 5}; std::replace_if(v.begin(), v.end(), [](int x){ return x < 3; }, 0); // v 变为: 0, 0, 3, 4, 5 </syntaxhighlight> === 填充操作 === ==== fill ==== 用特定值填充序列。 <syntaxhighlight lang="cpp"> std::vector<int> v(5); std::fill(v.begin(), v.end(), 42); // v 包含: 42, 42, 42, 42, 42 </syntaxhighlight> === 生成操作 === ==== generate ==== 使用生成函数填充序列。 <syntaxhighlight lang="cpp"> std::vector<int> v(5); int n = 1; std::generate(v.begin(), v.end(), [&n]{ return n++; }); // v 包含: 1, 2, 3, 4, 5 </syntaxhighlight> === 删除操作 === ==== remove ==== 从序列中"移除"等于特定值的元素(实际是将不删除的元素移到前面)。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 2, 3, 2, 1}; auto new_end = std::remove(v.begin(), v.end(), 2); v.erase(new_end, v.end()); // v 现在包含: 1, 3, 1 </syntaxhighlight> ==== remove_if ==== 根据谓词条件"移除"元素。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 2, 3, 4, 5}; auto new_end = std::remove_if(v.begin(), v.end(), [](int x){ return x % 2 == 0; }); v.erase(new_end, v.end()); // v 现在包含: 1, 3, 5 </syntaxhighlight> === 唯一化操作 === ==== unique ==== 移除相邻的重复元素。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 1, 2, 2, 3, 3, 3, 4}; auto new_end = std::unique(v.begin(), v.end()); v.erase(new_end, v.end()); // v 现在包含: 1, 2, 3, 4 </syntaxhighlight> === 反转和旋转 === ==== reverse ==== 反转序列中元素的顺序。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 2, 3, 4, 5}; std::reverse(v.begin(), v.end()); // v 现在包含: 5, 4, 3, 2, 1 </syntaxhighlight> ==== rotate ==== 旋转序列中的元素。 <syntaxhighlight lang="cpp"> std::vector<int> v = {1, 2, 3, 4, 5}; std::rotate(v.begin(), v.begin() + 2, v.end()); // v 现在包含: 3, 4, 5, 1, 2 </syntaxhighlight> === 随机重排 === ==== shuffle ==== 使用随机数生成器重排序列。 <syntaxhighlight lang="cpp"> #include <random> std::vector<int> v = {1, 2, 3, 4, 5}; std::random_device rd; std::mt19937 g(rd()); std::shuffle(v.begin(), v.end(), g); // v 现在是随机顺序,如: 3, 1, 5, 2, 4 </syntaxhighlight> == 性能考虑 == 修改序列操作的性能通常为线性时间复杂度O(n),其中n是序列长度。但某些操作如<code>remove</code>和<code>unique</code>需要配合<code>erase</code>才能真正减少容器大小,这可能导致额外的内存分配和释放。 == 实际应用案例 == === 案例1:数据清洗 === 从用户输入中移除所有无效数据: <syntaxhighlight lang="cpp"> struct Data { int id; std::string value; bool valid; }; void clean_data(std::vector<Data>& dataset) { dataset.erase( std::remove_if(dataset.begin(), dataset.end(), [](const Data& d) { return !d.valid; }), dataset.end() ); } </syntaxhighlight> === 案例2:游戏开发中的对象管理 === 在游戏循环中移除所有被标记为删除的对象: <syntaxhighlight lang="cpp"> class GameObject { public: bool should_be_removed; // 其他成员... }; void update_game_objects(std::vector<GameObject*>& objects) { objects.erase( std::remove_if(objects.begin(), objects.end(), [](GameObject* obj) { return obj->should_be_removed; }), objects.end() ); } </syntaxhighlight> === 案例3:数据处理流水线 === 实现一个简单的数据处理流水线: <syntaxhighlight lang="cpp"> std::vector<int> process_data(std::vector<int> input) { // 1. 移除所有负值 input.erase( std::remove_if(input.begin(), input.end(), [](int x) { return x < 0; }), input.end() ); // 2. 将所有偶数替换为它们的平方 std::transform(input.begin(), input.end(), input.begin(), [](int x) { return x % 2 == 0 ? x * x : x; }); // 3. 移除重复项 std::sort(input.begin(), input.end()); input.erase(std::unique(input.begin(), input.end()), input.end()); return input; } </syntaxhighlight> == 算法比较表 == {| class="wikitable" |+ 常用修改序列操作比较 ! 算法 !! 功能 !! 是否修改容器大小 !! 时间复杂度 |- | copy || 复制元素 || 否 || O(n) |- | move || 移动元素 || 否 || O(n) |- | replace || 替换元素 || 否 || O(n) |- | fill || 填充元素 || 否 || O(n) |- | remove || "移除"元素 || 需要配合erase || O(n) |- | unique || 移除相邻重复 || 需要配合erase || O(n) |- | reverse || 反转序列 || 否 || O(n) |- | rotate || 旋转序列 || 否 || O(n) |- | shuffle || 随机重排 || 否 || O(n) |} == 常见问题 == === Q: remove为什么不会真正删除元素? === A: <code>remove</code>算法只是将不删除的元素移动到序列前面,并返回新的逻辑结束位置。这是为了保持算法通用性,因为STL算法通常不知道如何调整底层容器的大小。要真正删除元素,需要配合容器的<code>erase</code>方法。 === Q: 如何选择copy和move? === A: 当源序列中的元素不再需要时,使用<code>move</code>可以避免不必要的拷贝,提高性能。但如果还需要保留源序列,则应使用<code>copy</code>。 === Q: 为什么有些算法需要先排序? === A: 像<code>unique</code>这样的算法只移除相邻的重复元素。如果要对整个序列去重,通常需要先排序使所有相同元素相邻。 == 最佳实践 == 1. 对于大型对象,优先考虑使用<code>move</code>而非<code>copy</code> 2. 使用<code>remove</code>或<code>unique</code>后,记得调用容器的<code>erase</code> 3. 考虑使用<code>std::back_inserter</code>等插入迭代器来避免预分配空间 4. 对于并行处理,C++17引入了并行版本的许多算法(如<code>std::for_each</code>的并行版本) == 总结 == C++ STL中的修改序列操作提供了强大而灵活的工具来处理容器数据。理解这些算法的行为、性能特征和适用场景,可以显著提高代码的简洁性和效率。这些算法遵循STL的设计哲学,通过迭代器抽象与特定容器解耦,提供了高度的通用性。 [[Category:编程语言]] [[Category:C++]] [[Category:C++stl 算法]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)