Day 31 C++ STL常用算法(下)

这篇具有很好参考价值的文章主要介绍了Day 31 C++ STL常用算法(下)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

常用拷贝和替换算法

copy——容器内指定范围的元素拷贝到另一容器中

函数原型
  • copy(iterator beg, iterator end, iterator dest);

    // 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

    // beg 开始迭代器

    // end 结束迭代器

    // dest 目标起始迭代器

注意——利用copy算法在拷贝时,目标容器要提前开辟空间
示例
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> source {1, 2, 3, 4, 5};
    std::vector<int> destination(5);  // 提前开辟目标容器空间

    std::copy(source.begin(), source.end(), destination.begin());

    // 输出目标容器中的内容
    for (auto i : destination) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:1 2 3 4 5

在上面的示例中,我们首先创建了一个源容器source,其中包含了一些整数。然后,我们创建了一个与源容器相同大小的目标容器destination,并且提前开辟了空间。

接下来,我们使用std::copy算法将源容器中的元素拷贝到目标容器中。通过传递源容器的迭代器source.begin()和source.end()以及目标容器的起始迭代器destination.begin()作为参数,实现了拷贝操作。

最后,遍历目标容器,并打印其中的元素

replace——将容器内指定范围的第一个旧元素修改为新元素

函数原型
  • replace(iterator beg, iterator end, oldvalue, newvalue);

    // 将区间内旧元素 替换成 新元素

    // beg 开始迭代器

    // end 结束迭代器

    // oldvalue 旧元素

    // newvalue 新元素

注意——replace只会替换区间内满足条件的第一个旧元素
示例
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec {1, 2, 3, 4, 5};

    std::replace(vec.begin(), vec.end(), 3, 9);

    // 输出修改后的容器内容
    for (auto i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:
1 2 9 4 5

在上面的示例中,我们首先创建了一个整数向量vec,其中包含了一些整数。然后,我们使用std::replace算法将容器中的旧元素3替换为新元素9。

通过传递容器的起始迭代器vec.begin()和结束迭代器vec.end()作为参数,以及要替换的旧元素3和新元素9,实现了替换操作。

最后,我们遍历容器,并打印其中的元素,可以看到被替换的元素已经被修改为新元素。

replace_if——在指定范围内将所有旧元素修改为新元素

函数原型
  • **replace_if(iterator beg, iterator end, _pred, newvalue); **

    // 按条件替换元素,满足条件的替换成指定元素

    // beg 开始迭代器

    // end 结束迭代器

    // _pred 谓词,谓词函数是一个返回布尔值的函数,用于确定元素是否满足某个条件。

    // 注意谓语是返回bool的仿函数,是谓词,是一个类,不是函数,但是可以当函数用
    // 因此可以利用仿函数灵活筛选满足的条件

    // newvalue 替换的新元素

注意——replace会替换区间内满足条件的所有旧元素

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec {1, 2, 3, 4, 5};

    std::replace_if(vec.begin(), vec.end(), [](int num){ return num == 3; }, 9);

    // 输出修改后的容器内容
    for (auto i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:
1 2 9 4 5

在这个示例中,我们使用了一个匿名的lambda函数作为谓词函数来判断元素是否需要被替换。lambda函数接受一个整数参数num,并返回一个bool值,判断这个整数是否等于3。如果等于3,则将其替换为新元素9。

通过使用lambda函数作为谓词函数,我们可以自定义替换的条件。在上述示例中,我们使用等于3的元素作为替换的条件。

需要注意的是,replace_if函数只会替换满足条件的第一个元素,如果想要替换所有满足条件的元素,可以考虑使用std::replace_copy_if或自定义循环进行处理。

swap——互换两个容器的元素

函数原型
  • swap(container c1, container c2);

    // 互换两个容器的元素

    // c1容器1

    // c2容器2

注意——swap交换容器时,注意交换的容器要同种类型

交换不同类型的容器,将会导致编译错误。

类型要匹配

要交换的容器类型要相同,或者满足可以进行隐式转换的条件。例如,两个 std::vector<int> 可以直接交换,但是 std::vector<int>std::vector<double> 之间不能直接交换。

容器的状态

交换容器时,要确保容器处于有效状态,即它们不应被移动、释放或销毁。否则,交换操作可能会导致未定义行为。

迭代器的失效

交换容器后,原来容器中的迭代器将会失效。如果有其他依赖于这些迭代器的代码,则需要谨慎处理,避免使用失效的迭代器。

容器的大小和内存开销

交换容器实际上是交换了它们的内部数据结构,这意味着会涉及到元素的复制或移动操作。如果容器的大小较大,交换操作可能会带来显著的内存开销和性能损失。

异常安全性

交换容器可能会引发异常,因此在交换操作之前,要考虑异常安全性,采取适当的措施来处理异常,以确保程序能够正常执行。

示例
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec1 {1, 2, 3};
    std::vector<int> vec2 {4, 5, 6};

    swap(vec1, vec2);

    // 输出交换后的vec1
    std::cout << "vec1: ";
    for (auto i : vec1) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // 输出交换后的vec2
    std::cout << "vec2: ";
    for (auto i : vec2) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:
vec1: 4 5 6
vec2: 1 2 3

在这个示例中,我们创建了两个vector类型的容器vec1和vec2。
然后,通过调用swap函数来交换这两个容器的元素。最
终,vec1中的元素变成了4, 5, 6,vec2中的元素变成了1, 2, 3。

常用算术生成算法

注意——算术生成算法属于小型算法,使用时包含的头文件为 #include <numeric>

accumulate—— 计算区间内容器元素累计总和

函数原型
  • accumulate(iterator beg, iterator end, value);

    // 计算容器元素累计总和

    // beg 开始迭代器

    // end 结束迭代器

    // value 起始值
    //起始值value是可选的,如果不提供该参数,那么默认起始值将是容器中的第一个元素的值。(看下面例子)

注意——如果容器为空,而且没有提供起始值参数,则调用accumulate函数会导致未定义行为

所以,在使用accumulate函数时,建议在累加之前检查容器是否非空,或者提供一个明确的起始值参数。

示例
#include <iostream>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> vec {1, 2, 3, 4, 5};

    int sum = std::accumulate(vec.begin(), vec.end());

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

输出结果为:
Sum: 15

在这个示例中,我们调用了accumulate函数来计算容器vec中元素的累计总和,但没有提供起始值参数。由于没有指定起始值,accumulate函数会使用容器中的第一个元素作为起始值进行累加运算。

因此,根据示例中的容器vec,累计总和仍然是15。

fill——用于将指定范围内的元素都设置为给定的值

函数原型
  • fill(iterator beg, iterator end, value);

    // 向容器中填充元素

    // beg 开始迭代器

    // end 结束迭代器

    // value 填充的值

注意——fill函数会将指点范围内所有元素都填充为给定的值,原本已的值会被覆盖。
示例
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec {1, 2, 3, 4, 5};

    std::fill(vec.begin(), vec.end(), 10);

    // 输出填充后的向量
    std::cout << "Filled Vector: ";
    for (auto i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:

Filled Vector: 10 10 10 10 10
在这个示例中,我们有一个包含初始值的向量vec,其中包含了数字1到5。然后,我们使用fill函数将容器vec中的所有元素都填充为10。

最终的输出结果显示,原本向量中的元素已经被覆盖,全部变成了10, 10, 10, 10, 10。

因此,需要注意,在使用fill函数时,如果你希望保留原有元素的值,只填充指定范围内的部分元素,可以使用更具灵活性的方法,如迭代器和算法结合使用来实现部分填充。

常用集合算法

set_intersection——求两个容器的交集

set_intersection 函数通常用于计算两个有序集合的交集。
但是,它实际上可以用于任何支持随机访问的序列容器,而不仅限于集合。

函数原型
  • set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
    // beg1 容器1开始迭代器
    // end1 容器1结束迭代器
    // beg2 容器2开始迭代器
    // end2 容器2结束迭代器
    // dest 目标容器开始迭代器
总结
  • 求交集的两个集合必须是有序序列
  • 目标容器开辟空间需要从两个容器中取小值
  • set_intersection返回值既是交集中最后一个元素的位置

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec1 {1, 2, 3, 4, 5};
    std::vector<int> vec2 {3, 4, 5, 6, 7};

    std::vector<int> intersection(std::min(vec1.size(), vec2.size()));

    auto it = std::set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), intersection.begin());

    // 输出交集中的元素
    std::cout << "Intersection: ";
    for (auto i = intersection.begin(); i != it; ++i) {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:
Intersection: 3 4 5

在这个示例中,我们有两个有序的向量vec1和vec2,分别包含了不同的整数。我们需要找出这两个向量的交集。

首先,我们创建了一个目标容器intersection,它的大小为两个输入容器中较小的那个。

然后,使用set_intersection函数将两个输入容器中的交集复制到目标容器intersection中。set_intersection函数接受五个参数,分别是两个输入容器的起始和结束迭代器,以及目标容器的起始迭代器。这样,交集中的元素就会复制到目标容器中。

最后,我们遍历目标容器中的元素,并输出交集中的值。

set_union——求两个集合的并集

函数原型
  • set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

    // beg1 容器1开始迭代器
    // end1 容器1结束迭代器
    // beg2 容器2开始迭代器
    // end2 容器2结束迭代器
    // dest 目标容器开始迭代器

总结(和set_intersection差不多)
  • 求并集的两个集合必须的有序序列
  • 目标容器开辟空间需要两个容器相加
  • set_union返回值既是并集中最后一个元素的位置
示例
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec1 {1, 2, 3, 4, 5};
    std::vector<int> vec2 {3, 4, 5, 6, 7};

    std::vector<int> unionSet(vec1.size() + vec2.size());

    auto it = std::set_union(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), unionSet.begin());

    // 输出并集中的元素
    std::cout << "Union: ";
    for (auto i = unionSet.begin(); i != it; ++i) {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:
Union: 1 2 3 4 5 6 7

在这个示例中,我们有两个有序的向量vec1和vec2,分别包含了不同的整数。我们需要找出这两个向量的并集。

首先,我们创建了一个目标容器unionSet,它的大小为两个输入容器的总大小。

然后,使用set_union函数将两个输入容器中的并集复制到目标容器unionSet中。
set_union函数接受五个参数,分别是两个输入容器的起始和结束迭代器,以及目标容器的起始迭代器。这样,并集中的元素就会复制到目标容器中。

最后,我们遍历目标容器中的元素,并输出并集中的值。

set_difference——求两个集合的差集

函数原型
  • set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

    // beg1 容器1开始迭代器
    // end1 容器1结束迭代器
    // beg2 容器2开始迭代器
    // end2 容器2结束迭代器
    // dest 目标容器开始迭代器

总结(都差不多)
  • 求差集的两个集合必须的有序序列
  • 目标容器开辟空间需要从两个容器取较大值
  • set_difference返回值既是差集中最后一个元素的位置

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec1 {1, 2, 3, 4, 5};
    std::vector<int> vec2 {3, 4, 5, 6, 7};

    std::vector<int> difference(std::max(vec1.size(), vec2.size()));

    auto it = std::set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), difference.begin());

    // 输出差集中的元素
    std::cout << "Difference: ";
    for (auto i = difference.begin(); i != it; ++i) {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果为:
Difference: 1 2

在这个示例中,我们有两个有序的向量vec1和vec2,分别包含了不同的整数。我们需要找出这两个向量的差集。

首先,我们创建了一个目标容器difference,它的大小为两个输入容器中较大的那个。

然后,使用set_difference函数将两个输入容器中的差集复制到目标容器difference中。
set_difference函数接受五个参数,分别是两个输入容器的起始和结束迭代器,以及目标容器的起始迭代器。这样,差集中的元素就会复制到目标容器中。

最后,我们遍历目标容器中的元素,并输出差集中的值。文章来源地址https://www.toymoban.com/news/detail-654038.html

到了这里,关于Day 31 C++ STL常用算法(下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法刷题Day 31 分发饼干+摆动序列+最大子序列和

    分发饼干其实有很多种写法,但是下面这种贪心的解法是最好理解,也最好解释的 我的其他解法 贪心算法 这道题用贪心算法要考虑的细节有很多。 动态规划 有点难(甚至涉及到了线段树),等后面二刷的时候再来学好了 暴力解法 超时了 贪心算法 贪心算法的代码写起来简

    2024年02月15日
    浏览(45)
  • day31贪心算法 用最少数量的箭引爆气球 和无重叠区间

    题目描述 题目分析: x轴向上射箭,12一支,重叠的需要一支,3-8一支,7-16一支 返回2; 就是让重叠的气球尽量在一起,局部最优;用一支弓箭,全局最优就是最少弓箭; 如何去寻找重叠的气球?和记录弓箭数? 1.对所有气球排序;(左边界排序如上图); 2. if 如果第i个气

    2024年02月16日
    浏览(48)
  • 算法训练day31贪心算法理论基础Leetcode455分发饼干376摆动序列53最大子序和

    文章链接 代码随想录 (programmercarl.com) 说实话贪心算法并没有固定的套路 。 最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧 。 面试中基本不会让面试者现场证明贪心的合理性,代码写出来跑过测试用例即可,或者自己能自圆其说理由就行了 。 刷题或者面

    2024年02月20日
    浏览(47)
  • 常用c++ STL 汇总

    vector 变长数组,倍增的思想 初始化: 操作: 遍历: 黑科技: 支持比较运算,按字典序比较 pair 二元组 初始化: 黑科技: 也支持比较运算 以first为第一,以second为第二 string 字符串 初始化: 操作: queue queue 队列 初始化:同数组 操作: priority_queue 优先队列

    2024年02月14日
    浏览(39)
  • C++,stl,常用排序算法,常用拷贝和替换算法

    目录 1.常用排序算法 sort random_shuffle merge reverse 2.常用拷贝和替换算法 copy replace replace_if swap 默认从小到大排序  使用的时候要加随机数种子            交换的容器要是同种类型

    2024年02月20日
    浏览(39)
  • Day31 贪心算法 part01 理论基础 455.分发饼干 376.摆动序列 53.最大子序和

    什么是贪心 贪心的本质是选择每一阶段的局部最优,从而达到全局最优 。 这么说有点抽象,来举一个例子: 例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿? 指定每次拿最大的,最终结果就是拿走最大数额的钱。 每次拿最大的就是局部最优,最

    2024年01月19日
    浏览(45)
  • STL常用算法

    目录 1 概述 2 常用遍历算法 2.1 for_each 2.2 transform 3 常用查找算法 3.1 find 3.2 find_if 3.3 adjacent_find 3.4 binary_search 3.5 count 3.6 count_if 4 常用排序算法 4.1 sort 4.2 random_shuffle 4.3 merge 4.4 reverse 5 常用拷贝和替换算法 5.1 copy 5.2 replace 5.3 replace_if 5.4 swap 6 常用算术生成算法 6.1 accumulate 6.2 fil

    2024年02月08日
    浏览(34)
  • STL- 常用算法

    概述 : 算法主要是由头文件 algorithm functional numeric 组成。 algorithm 是所有STL头文件中最大的一个,范围涉及到比较、 交换、查找、遍历操作、复制、修改等等 numeric 体积很小,只包括几个在序列上面进行简单数学运算的模板函数 functional 定义了一些模板类,用以声明函数对象。

    2024年02月09日
    浏览(40)
  • STL中的常用算法详解

    STL的算法主要是由下面的头文件组成的。 1.algorithm是所有STL头文件中最大的一个范围涉及到比较、交换、查找、遍历操作、复制、修改等等算法的头文件。 2.numeric体积很小,只包括几个再序列上面进行简单数学运算的模板函数。 3.functional定义了一些模板类,用以声明函数对

    2024年02月15日
    浏览(41)
  • 第九层(16):STL终章——常用集合算法

    🎉welcome🎉 ✒️博主介绍:一名大一的智能制造专业学生,在学习C/C++的路上会越走越远,后面不定期更新有关C/C++语法,数据结构,算法,Linux,ue5使用,制作游戏的心得,和大家一起共同成长。 ✈️C++专栏:C++爬塔日记 😘博客制作不易,👍点赞+⭐收藏+➕关注 在上一块

    2024年02月02日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包