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

c++ stl常用算法

目录

1.算法介绍

算法概述

STL中算法分类

常用算法汇总

2.常用算法用法示例

遍历

for_each

transform

for_each和transform对比

查找

adjacent_find

binary_search

count

count_if

find

find_if

排序

merge

sort

random_shuffle

reverse

拷贝和替换

copy

replace

replace_if

swap

算术运算

accumulate

fill

集合运算


1.算法介绍

算法概述

  • 算法部分主要由头文件<algorithm>,<functional>和<numeric>组成。
    • <algorithm>是所有STL头文件中最大的一个,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、反转、排序、合并等等。
    • <functional>中则定义了一些模板类,用以声明函数对象。
    • <numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
  • STL提供了大量实现算法的模版函数,只要我们熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能,从而大大地提升效率。

STL中算法分类

  • 操作对象 
    • 直接改变容器的内容
    • 将原容器的内容复制一份,修改其副本,然后传回该副本
  • 功能: 
    • 非可变序列算法 指不直接修改其所操作的容器内容的算法
      • 计数算法 count、count_if
      • 搜索算法 search、find、find_if、find_first_of、…
      • 比较算法 equal、mismatch、lexicographical_compare
    • 可变序列算法 指可以修改它们所操作的容器内容的算法
      • 删除算法 remove、remove_if、remove_copy、…
      • 修改算法 for_each、transform
      • 排序算法 sort、stable_sort、partial_sort、
    • 排序算法 包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作
    • 数值算法 对容器内容进行数值计算

常用算法汇总

  • 常用的遍历算法:
    • for_each(), transform()( 变换)
  • 常用的查找算法:
    • adjacent_find()(邻近),binary_search(),count(),
    • count_if(),equal_range(),find(),find_if()。
  • 常用的排序算法:
    • merge(),sort(),random_shuffle()(洗牌) ,reverse()。
  • 常用的拷贝和替换算法:
    • copy(), replace(),
    • replace_if(),swap()
  • 常用的算术和生成算法:
    • accumulate()( 求和),fill(),。
  • 常用的集合算法:
    • set_union(),set_intersection(),
    • set_difference()。

2.常用算法用法示例

遍历

for_each

  • for_each:  用指定函数依次对指定范围内所有元素进行迭代访问。该函数不会修改序列中的元素。
  • 函数使用:for_each(begin, end, func);

for_each函数原型理解(注意返回类型, 注意_Function __f这里不是引用)

注意for_each的第三个参数 函数对象做函数参数,函数对象做返回值

template<class _InIt,
class _Fn1> inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Func);
return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func));
}

例子

#include <iostream>
#include <string>
#include <vector>
#include <list>#include <algorithm>
#include <functional>using namespace std;template <typename T>
void printVec(vector<T> vec)
{auto it = vec.begin();for (it; it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}template <typename T>
void printList(list<T> lst)
{auto it = lst.begin();for (it; it != lst.end(); it++){cout << *it << "\t";}cout << endl;
}void showElement(int n)
{cout << n << "\t";
}class MyShow
{
public:MyShow(){num = 0;}void operator()(int n){num++;cout << n << "\t";}void printNum(){cout << "num=" << num << endl;}
protected:
private:int num;
};void test()
{vector<int> v1 = {1, 3, 5};printVec(v1);// 1.for_each算法对接普通回调函数for_each(v1.begin(), v1.end(), showElement);cout << endl;// 2.for_each算法对接匿名函数对象for_each(v1.begin(), v1.end(), MyShow());cout << endl;// 3.for_each算法对接函数对象MyShow myshow;MyShow temp_myshow = for_each(v1.begin(), v1.end(), myshow);cout << endl;// 查看myshow运算符()的调用次数myshow.printNum();         // 0temp_myshow.printNum();    // 3temp_myshow = for_each(v1.begin(), v1.end(), myshow);cout << endl;temp_myshow.printNum();    // 3}int main()
{// test for for_eachtest();return 0;
}

transform

transform:   与for_each类似,遍历所有元素,但可对容器的元素进行修改

transform()算法有两种形式:

第一种:transform(b1, e1, b2, op) 。可以一个容器的元素,通过op,变换到另一个容器中(同一个容器中)。将b1到e1中的每个元素通过op函数操作后的返回值从b2位置开始替换

第二种:transform(b1, e1, b2, b3, op) 。也可以把两个容器的元素,通过op,变换到另一个容器中

函数原型1

template<class _InIt,
class _OutIt,
class _Fn1> inline
_OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)

函数原型2

template<typename _InputIterator, typename _OutputIterator,typename _UnaryOperation>_OutputIteratortransform(_InputIterator __first, _InputIterator __last,_OutputIterator __result, _UnaryOperation __unary_op){// concept requirements__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,// "the type returned by a _UnaryOperation"__typeof__(__unary_op(*__first))>)__glibcxx_requires_valid_range(__first, __last);for (; __first != __last; ++__first, (void)++__result)*__result = __unary_op(*__first);return __result;}

例子

#include <iostream>
#include <string>
#include <vector>
#include <list>#include <algorithm>
#include <functional>
#include "iterator"using namespace std;template <typename T>
void printVec(vector<T> vec)
{auto it = vec.begin();for (it; it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}template <typename T>
void printList(vector<T> lst)
{auto it = lst.begin();for (it; it != lst.end(); it++){cout << *it << "\t";}cout << endl;
}int increase(int i)
{return i + 100;
}void test()
{vector<int> v1 = {1, 3, 5};printVec(v1);   // 1    3   5// 1.transform算法使用自定义的回调函数vector<int> v2;v2.resize(v1.size());transform(v1.begin(), v1.end(), v2.begin(), increase);printVec(v1);  // 1 3   5printVec(v2);  // 101   103 105// 2.transform算法修改容器本身transform(v1.begin(), v1.end(), v1.begin(), increase);printVec(v1);  // 101   103 105// 3.transform算法 使用 预定义的函数对象transform(v1.begin(), v1.end(), v1.begin(), negate<int>());printVec(v1);  // -101  -103    -105// 4.transform算法 使用函数适配器和函数对象transform(v1.begin(), v1.end(), v1.begin(), bind2nd(multiplies<int>(), 10));printVec(v1);  // -1010 -1030   -1050// 5.transform也可以把结果输出到屏幕上而不是输出到其它容器中// 注意头文件 "iterator"transform(v1.begin(), v1.end(), ostream_iterator<int>(cout, "\t"), negate<int>());// 屏幕会打印:1010   1030    1050cout << endl;printVec(v1);  // -1010 -1030   -1050}int main()
{// test for for_eachtest();return 0;
}

for_each和transform对比

  • ①使用比较
    • 一般情况下:for_each所使用的函数对象,参数是引用,没有返回值
void mysquare(int &num)
{num = num * num;
}
    • transform所使用的函数对象,参数一般不使用引用,而是还有返回值
int mysquare2(int num) //结果的传出,必须是通过返回值
{return num = num * num;
}
  • ②速度和灵活度比较
    • for_each() 速度快 用法不灵活
    • transform() 速度慢 用法非常灵活

函数原型

 template<typename _InputIterator, typename _Function>_Functionfor_each(_InputIterator __first, _InputIterator __last, _Function __f){// concept requirements__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)__glibcxx_requires_valid_range(__first, __last);for (; __first != __last; ++__first)__f(*__first);return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant.}template<typename _InputIterator, typename _OutputIterator,typename _UnaryOperation>_OutputIteratortransform(_InputIterator __first, _InputIterator __last,_OutputIterator __result, _UnaryOperation __unary_op){// concept requirements__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,// "the type returned by a _UnaryOperation"__typeof__(__unary_op(*__first))>)__glibcxx_requires_valid_range(__first, __last);for (; __first != __last; ++__first, (void)++__result)*__result = __unary_op(*__first);return __result;}

代码示例理解

#include <iostream>
#include <string>
#include <vector>#include <algorithm>
#include <functional>using namespace std;template <typename T>
void printVec(vector<T> vec)
{auto it = vec.begin();for (it; it != vec.end(); it++) {cout << *it << "\t";}cout << endl;
}void showElement(int &n)
{cout << n << "\t";n = n * 2;// 无返回值
}int showElement2(int n)
{cout << n << "\t";return n;  // 注意有返回值
}void test()
{vector<int> v1 = {1, 3, 5};vector<int> v2 = v1;// 一般情况下:for_each所使用的函数对象,参数是引用,没有返回值for_each(v1.begin(), v1.end(), showElement);   // 1 3   5cout << endl;   printVec(v1);  // 2 6   10cout << endl;  // transform所使用的函数对象,参数一般不使用引用,而是还有返回值transform(v2.begin(), v2.end(), v2.begin(), showElement2);  // 1    3   5cout << endl;printVec(v2);  // 1 3   5
}int main()
{// test for for_eachtest();return 0;
}

查找

adjacent_find

在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器。否则返回迭代器尾部。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void test()
{std::vector<int> v1 = {1, 2, 2, 3, 5};std::vector<int>::iterator it = adjacent_find(v1.begin(), v1.end());if (it == v1.end()) {cout << "未找到相邻相同元素" << endl;} else {cout << "找到相邻相同元素" << endl;cout << "第一个数:" << *it << endl;it++;cout << "第二个数:" << *it << endl;}}int main()
{test();return 0;
}

在有序序列中查找value,二分查找,找到则返回true。

注意:在无序序列中,不可使用。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void test()
{std::vector<int> v1 = {1, 3, 5, 7, 9};bool ret_bool = binary_search(v1.begin(), v1.end(), 7);if (ret_bool) {cout << "找到了" << endl;} else {cout << "未找到" << endl;}}int main()
{test();return 0;
}

count

利用等于操作符,把标志范围内的元素与输入值比较,返回相等的个数。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void test()
{std::vector<int> v1 = {1, 3, 5, 7, 7, 9, 7};int num = count(v1.begin(), v1.end(), 7);cout << num << endl;  // 3}int main()
{test();return 0;
}

count_if

自定义返回值为bool类型的函数,统计个数返回true的个数

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;// 是否是3的倍数
bool div_three(int num)
{if (num - num / 3 * 3 == 0) {return true;}return false;
}void test()
{vector<int> v1 = {1, 3, 5, 7, 7, 9, 7};int num = count_if(v1.begin(), v1.end(), div_three);cout << num << endl;  // 2
}int main()
{test();return 0;
}

find

find:  利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的迭代器。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void test()
{vector<int> v1 = {1, 3, 5, 7, 7, 9, 7};vector<int>::iterator it = find(v1.begin(), v1.end(), 5);if (it == v1.end()) {cout << "not found" << endl;} else {cout << *it << endl;  // 5}}int main()
{test();return 0;
}

find_if

find_if:   使用输入的函数代替等于操作符执行find。返回被找到的元素的迭代器。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;// 是否是3的倍数
bool div_three(int num)
{if (num - num / 3 * 3 == 0) {return true;}return false;
}void test()
{vector<int> v1 = {1, 3, 5, 7, 7, 9, 7};// 第一个能整除3的位置vector<int>::iterator it = find_if(v1.begin(), v1.end(), div_three);if (it == v1.end()) {cout << "not found" << endl;} else {cout << *it << endl;  // 3it++;cout << *it << endl;  // 5}}int main()
{test();return 0;
}

排序

merge

merge:    合并两个有序序列,存放到另一个序列(自动排序)。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 7};vector<int> v2 = {2, 4, 5, 6};vector<int> v3;v3.resize(v1.size() + v2.size());merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());printV(v3);  // 1   2   3   4   5   6   7
}int main()
{test();return 0;
}

sort

sort:  以默认升序的方式重新排列指定范围内的元素。若要改排序规则,可以输入比较函数。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;class Student
{
public:Student(string name, int id){m_name = name;m_id = id;}void printT(){cout << "name:" << m_name << "\tid:" << m_id << endl;}
protected:
public:string m_name;int m_id;};// sort函数会改变容器的值,所以这里用引用
bool CompareStudent(Student &stu1, Student &stu2)
{return (stu1.m_id < stu2.m_id);  // 升序
}void test()
{Student s1("老大", 1);Student s2("老二", 2);Student s3("老三", 3);Student s4("老四", 4);vector<Student> v1;v1.push_back(s4);v1.push_back(s1);v1.push_back(s3);v1.push_back(s2);for (vector<Student>::iterator it = v1.begin(); it != v1.end(); it++){it->printT();}/*name:老四 id:4name:老大 id:1name:老三 id:3name:老二 id:2*/// sort 根据自定义的函数进行排序sort(v1.begin(), v1.end(), CompareStudent);for (vector<Student>::iterator it = v1.begin(); it != v1.end(); it++) {it->printT();}/*name:老大 id:1name:老二 id:2name:老三 id:3name:老四 id:4*/}int main()
{test();return 0;
}

random_shuffle

srand(time(0)); //设置随机种子

random_shuffle:     对指定范围内的元素随机调整次序。

#include <iostream>
#include <vector>#include <stdlib.h>  // srand需要
#include <ctime>  // time(0)需要#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 5, 7};// 设置随机数种子srand(time(0)); // 注意不设随机数种子的话,每次乱序的结果是一样random_shuffle(v1.begin(), v1.end());printV(v1);  string str = "abcdefg";random_shuffle(str.begin(), str.end());cout << str << endl;}int main()
{test();return 0;
}

reverse

反转

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 5, 7};reverse(v1.begin(), v1.end());printV(v1);  // 7   5   3   1}int main()
{test();return 0;
}

拷贝和替换

copy

拷贝

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 5, 7};vector<int> v2;v2.resize(v1.size());copy(v1.begin(), v1.end(), v2.begin());printV(v2);  // 1   3   5   7}int main()
{test();return 0;
}

replace

replace(beg, end, oldValue, newValue):    将指定范围内的所有等于oldValue的元素替换成newValue。

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 5, 7, 3};replace(v1.begin(), v1.end(), 3, 9);printV(v1);  // 1   9   5   7   9}int main()
{test();return 0;
}

replace_if

满足条件则替换为指定值

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}// 是否大于等于5
bool great_equal_5(int &n)
{if (n >= 5){return true;}return false;
}void test()
{vector<int> v1 = {1, 3, 5, 7, 3};// 如果great_equal_5函数返回真,则替换为100replace_if(v1.begin(), v1.end(), great_equal_5, 100);printV(v1);  // 1   3   100 100 3}int main()
{test();return 0;
}

swap

swap:   交换两个容器的元素

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 5};vector<int> v2 = {2, 4, 6, 8};swap(v1, v2);printV(v1);  // 2   4   6   8printV(v2);  // 1   3   5}int main()
{test();return 0;
}

算术运算

accumulate

  • accumulate:  对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。
  • #include <numeric>
#include <iostream>
#include <vector>#include <algorithm>
#include <functional>
#include <numeric>using namespace std;void test()
{vector<int> v1;v1.push_back(1);v1.push_back(3);v1.push_back(5);int tmp = accumulate(v1.begin(), v1.end(), 100);cout << tmp << endl;  // 109}int main()
{test();return 0;
}

fill

fill: 将输入值赋给标志范围内的所有元素

#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1 = {1, 3, 5, 7, 9};auto it_start = v1.begin();it_start++;auto it_end = v1.end();it_end--;fill(it_start, it_end, 8);printV(v1);  // 1   8   8   8   9}int main()
{test();return 0;
}

集合运算

set_union(),set_intersection(),set_difference()

  • set_union:  构造一个有序序列,包含两个有序序列的并集。
  • set_intersection:  构造一个有序序列,包含两个有序序列的交集。
  • set_difference:  构造一个有序序列,该序列保留第一个有序序列中存在而第二个有序序列中不存在的元素。
#include <iostream>
#include <vector>#include <algorithm>
#include <functional>using namespace std;void printV(vector<int> vec)
{for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++){cout << *it << "\t";}cout << endl;
}void test()
{vector<int> v1;v1.push_back(1);v1.push_back(3);v1.push_back(5);vector<int> v2;v2.push_back(2);v2.push_back(4);v2.push_back(6);vector<int> v3;v3.resize(v1.size() + v2.size());// 并集set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());printV(v3);  // 1   2   3   4   5   6// 交集fill(v3.begin(), v3.end(), 0);set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());printV(v3);  // 0   0   0   0   0   0// 差集fill(v3.begin(), v3.end(), 0);set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());printV(v3);  // 1   3   5   0   0   0
}int main()
{test();return 0;
}


end

相关文章:

  • Lifecycle 核心原理面试回答
  • 标签管理软件_PICK_system_V1.2
  • [Css]等腰梯形
  • constexpr 是 C++11 引入的关键字
  • 【黄金评论】美元走强压制金价:基于NLP政策因子与ARIMA-GARCH的联动效应解析
  • 点评中是如何实现短信登录的
  • [蓝桥杯]对局匹配
  • FreeRTOS、Zephyr、RT-Thread,区别与联系
  • 回归分析-非线性回归及岭回归.docx
  • SIPp:SIP 协议性能测试工具!全参数详细教程!Kali Linux教程!
  • 瀚文机械键盘固件开发详解:HWKeyboard.cpp文件解析与应用
  • 物联网控制技术期末复习 知识点总结 第二章 单片机
  • 34.1STM32下的can总线实现知识(区分linux)_csdn
  • java判断一个字符串(如 str1)是否在给定的一组字符串
  • linux如何配置wifi连接
  • 微信小程序开发一个自定义组件的详细教程
  • LLM应用开发(九)- 幻觉及如何缓解
  • gateway 网关 路由新增 (已亲测)
  • HarmonyOS 实战:给笔记应用加防截图水印
  • EMCC 13c 报错 “Metrics Global Cache Blocks Lost is at XXX“ 解决
  • 黄村网站建设一条龙/小网站搜什么关键词
  • 微信网站建设哪家好/百度搜索热度指数
  • 网站建设排行榜/媒体推广
  • 网站建设做什么/百度app安装免费下载
  • 上海浦东建筑建设网站污水处理工程/新网站排名优化怎么做
  • 如何加强企业网站建设 论文/网页怎么做