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

STL常用算法——C++

1.概述

2.常用遍历算法

1.简介

2.for_each

方式一:传入普通函数(printf1)

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void printf1(int a)
{cout << a << " ";
}
int main()
{vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}for_each(v.begin(), v.end(), printf1);cout << endl;return 0;
}

方式2:利用仿函数,传入匿名函数对象

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:void operator()(int a){cout << a << " ";}
};
int main()
{vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}for_each(v.begin(), v.end(), person());cout << endl;return 0;
}

注意:函数只需要传入函数名就行,但是仿函数需要传入函数对象。

for_each在实际开发中是最常用的一个算法,需要熟练掌握

3.transform

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class transform1
{
public:int operator()(int a){return a;}
};
class print
{
public:void operator()(int a){cout<<a<<" ";}
};
int main()
{vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}vector<int>v1;v1.resize(v.size());transform(v.begin(), v.end(), v1.begin(), transform1());for_each(v.begin(), v.end(), print());cout << endl;return 0;
}

注意:转运之前,需要将目标对象用resize()也开辟相同的空间。

3.常用查找算法

1.find

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:person(string name, int age){this->name = name;this->age = age;}bool operator==(const person& p){if (this->age == p.age && this->name == p.name){return true;}else return false;}string name;int age;
};
int main()
{vector<person> v;person p1("1", 12);person p2("2", 13);person p3("3", 14);person p4("4", 15);person p5("5", 16);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);v.push_back(p5);vector<person>::iterator it = find(v.begin(), v.end(), p2);if (it == v.end()){cout << "没有找到" << endl;}else{cout << "找到了" << endl;}return 0;
}

或者也可以将查找条件改为

    person pp(”11“,13);

    vector<person>::iterator it = find(v.begin(), v.end(), pp);

注意:find的返回值是迭代器

2.find_if

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}vector<int>::iterator it=find_if(v.begin(), v.end(), person());if (it == v.begin()){cout << "没有找到" << endl;}else{cout << "找到了:" << *it << endl;}return 0;
}

3.abjacent_find

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
int main()
{vector<int> v;v.push_back(1);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(3);v.push_back(4);vector<int>::iterator it=adjacent_find(v.begin(), v.end());if (it == v.end()){cout << "没有找到" << endl;}else{cout << "找到了:" << *it << endl;}return 0;
}

4.binary_search

底层原理就是二分查找,二分查找需要提前排序好才能用,二分查找需要的算力少。

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
int main()
{vector<int> v;for(int i=0;i<10;i++){v.push_back(i);}bool ret = binary_search(v.begin(), v.end(),9);if (ret){cout << "找到了" << endl;}else{cout << "没找到" << endl;}return 0;
}

如果是无序序列,结果未知

5.count

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:person(string name, int age){this->age = age;this->name = name;}bool operator==(const person& p){if (p.age == this->age){return true;}else{return false;}}int age;string name;
};
int main()
{vector<person> v;person p1("刘备", 35);person p2("关羽", 35);person p3("张飞", 35);person p4("赵云", 20);person p5("刘备", 40);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);v.push_back(p5);person p("诸葛亮", 35);int a = count(v.begin(), v.end(), p);cout << "同年龄的有:" << a << "个" << endl;return 0;
}

关于为什么operator要加const

const Person p1("刘备", 35);

Person p2("关羽", 35);

if (p1 == p2)

{

// 编译错误:无法将 const 对象传递给非 const 引用参数

cout << "年龄相同" << endl;

}

在运算符重载中,参数通常也会被声明为const。这样做的目的是为了扩大函数的适用范围,使其既能接受const对象,也能接受非const对象。

总结:对于统计自定义数据类型的时候,需要配合重载operator==

           对于形参是自定义类型时,要加上const

6.count_if

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:bool operator()(int val){return val == 2;}
};
int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(2);v.push_back(2);v.push_back(5);int a = count_if(v.begin(), v.end(), person());cout << "同年龄的有:" << a << "个" << endl;return 0;
}

4.常用排序算法

1.sort

pred是谓词

生序

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void print(int a)
{cout << a << " ";
}
int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(6);v.push_back(3);v.push_back(5);sort(v.begin(), v.end());for_each(v.begin(), v.end(), print);return 0;
}

降序(利用内建函数对象greater实现降序排序,要包含头文件functional)

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{cout << a << " ";
}
int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(6);v.push_back(3);v.push_back(5);sort(v.begin(), v.end(), greater<int>());for_each(v.begin(), v.end(),fun);return 0;
}

2.random_shuffle

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{cout << a << " ";
}
int main()
{vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}random_shuffle(v.begin(), v.end());for_each(v.begin(), v.end(),fun);return 0;
}

可以加入时间种子来达到真随机效果(srand(unsigned int)time(NULL);)

不过需要包含头文件#include<time.h>

3.merge

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{cout << a << " ";
}
int main()
{vector<int> v1;vector<int> v2;vector<int> v3;for (int i = 0; i < 10; i++){v1.push_back(i);v2.push_back(i+1);}v3.resize(v1.size() + v2.size());merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());for_each(v3.begin(), v3.end(),fun);return 0;
}

不过要给目标容器提前开辟内存空间用resize

而且合并之后还是一个有序序列

merge合并的两个序列必须是有序序列

4.reverse

5.常用拷贝和替换算法

1.copy

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{cout << a << " ";
}
int main()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++){v1.push_back(i);}v2.resize(v1.size());copy(v1.begin(), v1.end(), v2.begin());for_each(v2.begin(), v2.end(),fun);return 0;
}

2.replace

3.replace_if

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{cout << a << " ";
}
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v1;for (int i = 0; i < 10; i++){v1.push_back(i);}replace_if(v1.begin(), v1.end(), person(), 1000);for_each(v1.begin(), v1.end(),fun);return 0;
}

可以利用仿函数灵活的设置筛选条件

4.swap

swap(v1,v2);

其中两个容器的大小和数值都会交换,不过交换的容器要同种类型

6.常用算术生成算法

1.accumulate

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{cout << a << " ";
}
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v1;for (int i = 0; i <= 100; i++){v1.push_back(i);}int val=accumulate(v1.begin(),v1.end(),0);/*for_each(v1.begin(), v1.end(),fun);*/cout << val << endl;return 0;
}

比较实用,记住要添加头文件#include<numeric>

2.fill

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{cout << a << " ";
}
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v1;for (int i = 0; i < 10; i++){v1.push_back(i);}fill(v1.begin(),v1.end(),99);for_each(v1.begin(), v1.end(),fun);cout << endl;vector<int> v2;v2.resize(10);fill(v2.begin(), v2.end(), 11);for_each(v2.begin(), v2.end(), fun);return 0;
}

如果已经有了数值,会把原来的数值顶替掉

7.常用集合算法

1.set_intersection

交集:即两个容器中数值相同的元素

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{cout << a << " ";
}
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++){v1.push_back(i);v2.push_back(i+3);}vector<int>v3;v3.resize(min(v1.size(), v2.size()));vector<int>::iterator it=set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());for_each(v3.begin(),it,fun);cout << endl;return 0;
}

注意:

set_intersection其中它会返回交际的最后一个元素的迭代器,遍历输出交集的时候不要写end(),要写它返回的迭代器,这样就不会输出无用元素。

存储交集的目标容器需要提前开辟空间,最特殊的情况是大容器包含小容器,即交集就是小容器,所以取小容器的大小即可。

min()包含在algorithm头文件中,找出最小值

2.set_union

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{cout << a << " ";
}
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++){v1.push_back(i);v2.push_back(i+3);}vector<int>v3;v3.resize(v1.size()+v2.size());vector<int>::iterator it=set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());for_each(v3.begin(),it,fun);cout << endl;return 0;
}

最坏的情况是一个相同的都没有,所以开辟大小直接把两个容器的大小加起来就行

注意:两个容器必须是有序序列

3.set_different

有两种差集的情况:(谁在前先求谁的差集)

#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{cout << a << " ";
}
class person
{
public:bool operator()(int val){return val > 5;}
};
int main()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++){v1.push_back(i);v2.push_back(i+3);}v2.push_back(99);vector<int>v3;v3.resize(max(v1.size(),v2.size()));vector<int>::iterator it=set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());for_each(v3.begin(),it,fun);cout << endl;vector<int>::iterator it1 = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v3.begin());for_each(v3.begin(), it1, fun);cout << endl;return 0;
}

注意:两个容器必须是有序序列

相关文章:

  • Unity 跳转资源商店,并打开特定应用
  • C# 事件知识文档
  • Vue2 el-checkbox 虚拟滚动解决多选框全选卡顿问题 - 高性能处理大数据量选项列表
  • 如何给文件增加拓展名
  • 1️⃣5️⃣three.js_GUI辅助调试器
  • Qt进阶开发:鼠标及键盘事件
  • AOSP Android14 Launcher3——RectFSpringAnim窗口动画类详解
  • ComfyUI+Sonic实战,三步实现图片开口说话
  • 单个或批量实现-提取PDF文档中的合同号和姓名并按“合同号_姓名”格式重命名文件。
  • 【文献分享】Model-based evaluation提供了数据和代码
  • day48—双指针-通过删除字母匹配到字典最长单词(LeetCode-524)
  • rk3568main.cc解析
  • 多路转接select服务器
  • Node.js简介(nvm使用)
  • docker-compose搭建kafka
  • Git Flow分支模型
  • L2-2、示范教学与角色扮演:激发模型“模仿力“与“人格“
  • 从单模态到多模态:深度生成模型的演进历程
  • 【武汉理工大学第四届ACM校赛】copy
  • EAL4+与等保2.0:解读中国网络安全双标准
  • 游客大理古城买瓜起争执:170克手机称出340克
  • 从神舟五号到神舟二十号,每次任务标识藏着哪些逐梦星辰的密码
  • 电商平台全面取消“仅退款”:电商反内卷一大步,行业回归良性竞争
  • 世界读书日丨上图东馆开启残疾人无障碍文化服务
  • 一条水脉串起七个特色区块,上海嘉定发布2025年新城行动方案
  • 广西出现今年首场超警洪水