【C++提高】算法

server/2025/3/15 4:29:40/

算法

  • 一、遍历算法
    • 1. for_each
    • 2. transform
  • 二、查找算法
    • 1. find
    • 2. find_if
    • 3. adjacent_find
    • 4. binary_search
    • 5. count
    • 6. count_if
  • 三、排序算法
    • 1. sort
    • 2. random_shuffle
    • 3. merge
    • 4. reverse
  • 四、拷贝和替换算法
    • 1. copy
    • 2. replace
    • 3. replace_if
    • 4. swap
  • 五、算术生成算法
    • 1. accumulate
    • 2. fill
  • 六、集合算法
    • 1. set_intersection
    • 2. set_union
    • 3. set_difference
  • 七、用法对比

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

一、遍历算法

1. for_each

实现遍历容器,函数原型为for_each(iterator beg, iterator end, _func); 。其中,beg为开始迭代器,end为结束迭代器,_func为函数或者函数对象。

#include <algorithm>
#include <vector>//普通函数
void print01(int val) 
{cout << val << " ";
}
//函数对象
class print02 
{public:void operator()(int val) {cout << val << " ";}
};//for_each算法基本用法
void test01() {vector<int> v;for (int i = 0; i < 10; i++) {v.push_back(i);}//遍历算法for_each(v.begin(), v.end(), print01);cout << endl;for_each(v.begin(), v.end(), print02());cout << endl;
}int main() {test01();system("pause");return 0;
}

2. transform

搬运容器到另一个容器中,函数原型为transform(iterator beg1, iterator end1, iterator beg2, _func);。其中,beg1为源容器开始迭代器,end1为源容器结束迭代器,beg2为目标容器开始迭代器,_func为函数或者函数对象。注意,目标容器需要提前开辟空间。

#include<vector>
#include<algorithm>//常用遍历算法  搬运 transformclass TransForm
{
public:int operator()(int val){return val;}};class MyPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int>v;for (int i = 0; i < 10; i++){v.push_back(i);}vector<int>vTarget; //目标容器vTarget.resize(v.size()); // 目标容器需要提前开辟空间transform(v.begin(), v.end(), vTarget.begin(), TransForm());for_each(vTarget.begin(), vTarget.end(), MyPrint());
}int main() {test01();system("pause");return 0;
}

二、查找算法

1. find

查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()。函数原型为find(iterator beg, iterator end, value); 。其中,beg为开始迭代器,end为结束迭代器,value为查找的元素。

#include <algorithm>
#include <vector>
#include <string>
void test01() {vector<int> v;for (int i = 0; i < 10; i++) {v.push_back(i + 1);}//查找容器中是否有 5 这个元素vector<int>::iterator it = find(v.begin(), v.end(), 5);if (it == v.end()) {cout << "没有找到!" << endl;}else {cout << "找到:" << *it << endl;}
}class Person {
public:Person(string name, int age) {this->m_Name = name;this->m_Age = age;}//重载==bool operator==(const Person& p) {if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {return true;}return false;}public:string m_Name;int m_Age;
};void test02() {vector<Person> v;//创建数据Person p1("aaa", 10);Person p2("bbb", 20);Person p3("ccc", 30);Person p4("ddd", 40);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);vector<Person>::iterator it = find(v.begin(), v.end(), p2);if (it == v.end()) {cout << "没有找到!" << endl;}else {cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;}
}

2. find_if

按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置。函数原型为find_if(iterator beg, iterator end, _Pred); 。其中,beg为开始迭代器,end为结束迭代器,_Pred为函数或者谓词(返回bool类型的仿函数)。

#include <algorithm>
#include <vector>
#include <string>//内置数据类型
class GreaterFive
{
public:bool operator()(int val){return val > 5;}
};void test01() {vector<int> v;for (int i = 0; i < 10; i++) {v.push_back(i + 1);}vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());if (it == v.end()) {cout << "没有找到!" << endl;}else {cout << "找到大于5的数字:" << *it << endl;}
}//自定义数据类型
class Person {
public:Person(string name, int age){this->m_Name = name;this->m_Age = age;}
public:string m_Name;int m_Age;
};class Greater20
{
public:bool operator()(Person &p){return p.m_Age > 20;}};void test02() {vector<Person> v;//创建数据Person p1("aaa", 10);Person p2("bbb", 20);Person p3("ccc", 30);Person p4("ddd", 40);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);vector<Person>::iterator it = find_if(v.begin(), v.end(), Greater20());if (it == v.end()){cout << "没有找到!" << endl;}else{cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;}
}int main() {//test01();test02();system("pause");return 0;
}

3. adjacent_find

查找相邻重复元素,返回相邻元素的第一个位置的迭代器。函数原型为adjacent_find(iterator beg, iterator end); 。其中,beg为开始迭代器,end为结束迭代器。

#include <algorithm>
#include <vector>void test01()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(5);v.push_back(2);v.push_back(4);v.push_back(4);v.push_back(3);//查找相邻重复元素vector<int>::iterator it = adjacent_find(v.begin(), v.end());if (it == v.end()) {cout << "找不到!" << endl;}else {cout << "找到相邻重复元素为:" << *it << endl;}
}

4. binary_search

查找指定的元素,查到返回true,否则返回false。该算法在无序序列中不可用。函数原型
bool binary_search(iterator beg, iterator end, value); 。其中,beg为开始迭代器,end为结束迭代器,value为查找的元素。

#include <algorithm>
#include <vector>void test01()
{vector<int>v;for (int i = 0; i < 10; i++){v.push_back(i);}//二分查找bool ret = binary_search(v.begin(), v.end(),2);if (ret){cout << "找到了" << endl;}else{cout << "未找到" << endl;}
}int main() {test01();system("pause");return 0;
}

5. count

统计元素出现次数。函数原型为count(iterator beg, iterator end, value);。其中,beg为开始迭代器,end为结束迭代器,value为统计的元素。

#include <algorithm>
#include <vector>//内置数据类型
void test01()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(4);v.push_back(5);v.push_back(3);v.push_back(4);v.push_back(4);int num = count(v.begin(), v.end(), 4);cout << "4的个数为: " << num << endl;
}//自定义数据类型
class Person
{
public:Person(string name, int age){this->m_Name = name;this->m_Age = age;}bool operator==(const Person & p){if (this->m_Age == p.m_Age){return true;}else{return false;}}string m_Name;int m_Age;
};void test02()
{vector<Person> v;Person p1("刘备", 35);Person p2("关羽", 35);Person p3("张飞", 35);Person p4("赵云", 30);Person p5("曹操", 25);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);v.push_back(p5);Person p("诸葛亮",35);int num = count(v.begin(), v.end(), p);cout << "num = " << num << endl;
}
int main() {//test01();test02();system("pause");return 0;
}

6. count_if

按条件统计元素出现次数。函数原型为count_if(iterator beg, iterator end, _Pred);。其中,beg为开始迭代器,end为结束迭代器,_Pred为函数或者谓词(返回bool类型的仿函数)。

#include <algorithm>
#include <vector>class Greater4
{
public:bool operator()(int val){return val >= 4;}
};//内置数据类型
void test01()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(4);v.push_back(5);v.push_back(3);v.push_back(4);v.push_back(4);int num = count_if(v.begin(), v.end(), Greater4());cout << "大于4的个数为: " << num << endl;
}//自定义数据类型
class Person
{
public:Person(string name, int age){this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age;
};class AgeLess35
{
public:bool operator()(const Person &p){return p.m_Age < 35;}
};
void test02()
{vector<Person> v;Person p1("刘备", 35);Person p2("关羽", 35);Person p3("张飞", 35);Person p4("赵云", 30);Person p5("曹操", 25);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);v.push_back(p5);int num = count_if(v.begin(), v.end(), AgeLess35());cout << "小于35岁的个数:" << num << endl;
}int main() {//test01();test02();system("pause");return 0;
}

三、排序算法

1. sort

对容器内元素进行排序。函数原型为sort(iterator beg, iterator end, _Pred);。其中,beg为开始迭代器,end为结束迭代器,_Pred为函数或者谓词(返回bool类型的仿函数)。

#include <algorithm>
#include <vector>void myPrint(int val)
{cout << val << " ";
}void test01() {vector<int> v;v.push_back(10);v.push_back(30);v.push_back(50);v.push_back(20);v.push_back(40);//sort默认从小到大排序sort(v.begin(), v.end());for_each(v.begin(), v.end(), myPrint);cout << endl;//从大到小排序sort(v.begin(), v.end(), greater<int>());for_each(v.begin(), v.end(), myPrint);cout << endl;
}int main() {test01();system("pause");return 0;
}

2. random_shuffle

指定范围内的元素随机调整次序。函数原型为random_shuffle(iterator beg, iterator end);。其中,beg为开始迭代器,end为结束迭代器。使用时记得加随机数种子srand((unsigned int)time(NULL));

#include <algorithm>
#include <vector>
#include <ctime>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{srand((unsigned int)time(NULL));vector<int> v;for(int i = 0 ; i < 10;i++){v.push_back(i);}for_each(v.begin(), v.end(), myPrint());cout << endl;//打乱顺序random_shuffle(v.begin(), v.end());for_each(v.begin(), v.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

3. merge

两个容器元素合并,并存储到另一容器中。函数原型为merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);。两个容器必须是有序的。其中,beg1是容器1开始迭代器,end1是容器1结束迭代器,beg2是容器2开始迭代器,end2是容器2结束迭代器,dest是目标容器开始迭代器。注意,目标容器需要提前开辟空间。

#include <algorithm>
#include <vector>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10 ; i++) {v1.push_back(i);v2.push_back(i + 1);}vector<int> vtarget;//目标容器需要提前开辟空间vtarget.resize(v1.size() + v2.size());//合并  需要两个有序序列merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vtarget.begin());for_each(vtarget.begin(), vtarget.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

4. reverse

将容器内元素进行反转。函数原型为reverse(iterator beg, iterator end);。其中,beg为开始迭代器,end为结束迭代器。

#include <algorithm>
#include <vector>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v;v.push_back(10);v.push_back(30);v.push_back(50);v.push_back(20);v.push_back(40);cout << "反转前: " << endl;for_each(v.begin(), v.end(), myPrint());cout << endl;cout << "反转后: " << endl;reverse(v.begin(), v.end());for_each(v.begin(), v.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

四、拷贝和替换算法

1. copy

容器内指定范围的元素拷贝到另一容器中。函数原型为copy(iterator beg, iterator end, iterator dest);。其中,beg为开始迭代器,end为结束迭代器,dest为目标开始迭代器。注意,需要提前为目标容器开辟空间。

#include <algorithm>
#include <vector>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v1;for (int i = 0; i < 10; i++) {v1.push_back(i + 1);}vector<int> v2;v2.resize(v1.size());copy(v1.begin(), v1.end(), v2.begin());for_each(v2.begin(), v2.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

2. replace

将容器内指定范围的旧元素修改为新元素。函数原型为replace(iterator beg, iterator end, oldvalue, newvalue);。其中,beg为开始迭代器,end为结束迭代器,oldvalue为旧元素,newvalue为新元素。

#include <algorithm>
#include <vector>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v;v.push_back(20);v.push_back(30);v.push_back(20);v.push_back(40);v.push_back(50);v.push_back(10);v.push_back(20);cout << "替换前:" << endl;for_each(v.begin(), v.end(), myPrint());cout << endl;//将容器中的20 替换成 2000cout << "替换后:" << endl;replace(v.begin(), v.end(), 20,2000);for_each(v.begin(), v.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

3. replace_if

将区间内满足条件的元素,替换成指定元素。函数原型为replace_if(iterator beg, iterator end, _pred, newvalue);。其中,beg为开始迭代器,end为结束迭代器,_Pred为函数或者谓词(返回bool类型的仿函数),newvalue为新元素。

#include <algorithm>
#include <vector>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};class ReplaceGreater30
{
public:bool operator()(int val){return val >= 30;}};void test01()
{vector<int> v;v.push_back(20);v.push_back(30);v.push_back(20);v.push_back(40);v.push_back(50);v.push_back(10);v.push_back(20);cout << "替换前:" << endl;for_each(v.begin(), v.end(), myPrint());cout << endl;//将容器中大于等于的30 替换成 3000cout << "替换后:" << endl;replace_if(v.begin(), v.end(), ReplaceGreater30(), 3000);for_each(v.begin(), v.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

4. swap

互换两个容器的元素。函数原型为swap(container c1, container c2);。其中,c1和c2为两个需要互换的容器。注意,互换的容器需要同种类型。

#include <algorithm>
#include <vector>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++) {v1.push_back(i);v2.push_back(i+100);}cout << "交换前: " << endl;for_each(v1.begin(), v1.end(), myPrint());cout << endl;for_each(v2.begin(), v2.end(), myPrint());cout << endl;cout << "交换后: " << endl;swap(v1, v2);for_each(v1.begin(), v1.end(), myPrint());cout << endl;for_each(v2.begin(), v2.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

五、算术生成算法

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

1. accumulate

计算区间内容器元素累计总和。函数原型为accumulate(iterator beg, iterator end, value);。其中,beg为开始迭代器,end为结束迭代器,value为叠加起始值。

#include <numeric>
#include <vector>
void test01()
{vector<int> v;for (int i = 0; i <= 100; i++) {v.push_back(i);}int total = accumulate(v.begin(), v.end(), 0);cout << "total = " << total << endl;
}int main() {test01();system("pause");return 0;
}

2. fill

向容器中填充指定的元素。函数原型为fill(iterator beg, iterator end, value);。其中,beg为开始迭代器,end为结束迭代器,value为填充的值。

#include <numeric>
#include <vector>
#include <algorithm>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v;v.resize(10);//填充fill(v.begin(), v.end(), 100);for_each(v.begin(), v.end(), myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

六、集合算法

1. set_intersection

求两个容器的交集。函数原型为set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);。其中,beg1为容器1开始迭代器,end1为容器1结束迭代器,beg2为容器2开始迭代器,end2为容器2结束迭代器,dest为目标容器开始迭代器,返回值为填充后的迭代器。注意,两个集合必须是有序序列,且目标容器需要提前开辟空间,目标容器开辟空间需要从两个容器中取小值。

#include <vector>
#include <algorithm>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++){v1.push_back(i);v2.push_back(i+5);}vector<int> vTarget;//取两个里面较小的值给目标容器开辟空间vTarget.resize(min(v1.size(), v2.size()));//返回目标容器的最后一个元素的迭代器地址vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());for_each(vTarget.begin(), itEnd, myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

2. set_union

求两个集合的并集。函数原型为set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);。其中,beg1为容器1开始迭代器,end1为容器1结束迭代器,beg2为容器2开始迭代器,end2为容器2结束迭代器,dest为目标容器开始迭代器,返回值为填充后的迭代器。注意,两个集合必须是有序序列,且目标容器需要提前开辟空间,目标容器开辟空间需要两个容器相加。

#include <vector>
#include <algorithm>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++) {v1.push_back(i);v2.push_back(i+5);}vector<int> vTarget;//取两个容器的和给目标容器开辟空间vTarget.resize(v1.size() + v2.size());//返回目标容器的最后一个元素的迭代器地址vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());for_each(vTarget.begin(), itEnd, myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

3. set_difference

求两个集合的差集。函数原型为set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);。其中,beg1为容器1开始迭代器,end1为容器1结束迭代器,beg2为容器2开始迭代器,end2为容器2结束迭代器,dest为目标容器开始迭代器,返回值为填充后的迭代器。注意,两个集合必须是有序序列,且目标容器需要提前开辟空间,目标容器开辟空间需要两个容器取较大值。

#include <vector>
#include <algorithm>class myPrint
{
public:void operator()(int val){cout << val << " ";}
};void test01()
{vector<int> v1;vector<int> v2;for (int i = 0; i < 10; i++) {v1.push_back(i);v2.push_back(i+5);}vector<int> vTarget;//取两个里面较大的值给目标容器开辟空间vTarget.resize( max(v1.size() , v2.size()));//返回目标容器的最后一个元素的迭代器地址cout << "v1与v2的差集为: " << endl;vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());for_each(vTarget.begin(), itEnd, myPrint());cout << endl;cout << "v2与v1的差集为: " << endl;itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget.begin());for_each(vTarget.begin(), itEnd, myPrint());cout << endl;
}int main() {test01();system("pause");return 0;
}

七、用法对比

算法是否支持操作set和map是否对内部数据顺序有要求是否支持内部数据为自定义类型
for_each支持无要求支持
transform支持无要求支持
find支持无要求支持但自定义类需要重载运算符==
find_if支持无要求支持但需要加入谓词做参数
adjacent_find不支持无要求支持但需要加入谓词做参数
swap支持无要求支持
binary_search支持必须升序不支持
count支持无要求支持但自定义类需要重载运算符==
count_if支持无要求支持但需要加入谓词做参数
sort不支持无要求支持但需要加入谓词做参数
random_shuffle不支持无要求支持
merge不支持必须升序不支持
reverse不支持无要求支持
copy不支持无要求支持
replace不支持无要求支持但自定义类需要重载运算符==
replace_if不支持无要求支持但需要加入谓词做参数
swap支持无要求支持
accumulate支持无要求支持
fill不支持无要求支持
set_intersection不支持必须升序不支持
set_union不支持必须升序不支持
set_difference不支持必须升序不支持

http://www.ppmy.cn/server/9888.html

相关文章

JMeter--监听器--聚合报告

聚合报告&#xff08;Aggregate Report&#xff09; 可以查看事务或者取样器在某个时间范围内执行的汇总结果 右键 >>> 添加 >>> 监听器 >>> 聚合报告&#xff08;Aggregate Report&#xff09; Label 样本平均值中位数90% 百分位95% 百分位99% …

Ruby中Rack中间件的作用是什么?如何应用?

在 Ruby 中&#xff0c;Rack 是一个 Web 服务器接口&#xff0c;它允许开发者使用统一的方式构建 Web 应用程序。Rack 中间件是 Rack 框架的一个核心概念&#xff0c;它可以在请求被传递给应用程序之前或之后对请求和响应进行处理。 Rack 中间件的作用包括但不限于&#xff1a…

Redis - Redisson tryLock 函数参数分析

这里有三个参数&#xff1a; waitTime&#xff1a;等待时间leaseTime&#xff1a;超时施放时间TimeUnit&#xff1a;时间单位 等待时间 如果 ABC… 多个线程去抢夺一把锁&#xff0c;A 成功了&#xff0c;如果设置的是 -1&#xff0c;那么 BCD... 就不等待&#xff0c;直接返…

【Hadoop】-拓展:蒙特卡罗算法求PI的基础原理[10]

Monte Carlo蒙特卡罗算法&#xff08;统计模拟法&#xff09; Monte Carlo算法的基本思想是&#xff1a;以模拟的“实验”形式、以大量随机样本的统计形式&#xff0c;来得到问题的求解。比如&#xff0c;求圆周率&#xff0c;以数学的方式是非常复杂的&#xff0c;但是我们可…

蓝桥杯刷题-乌龟棋

312. 乌龟棋 - AcWing题库 /* 状态表示&#xff1a;f[b1,b2,b3,b4]表示所有第 i种卡片使用了 bi张的走法的最大分值。状态计算&#xff1a;将 f[b1,b2,b3,b4]表示的所有走法按最后一步选择哪张卡片分成四类&#xff1a;第 i类为最后一步选择第 i种卡片。比如 i2&#xff0c;则…

DBA搞钱之路

DBA 中文叫数据库管理员,从最初什么什么图书管理员升级上来的.图书管理员是管理图书的,图书包含了大量的知识.而数据库管理员是管理企业和机构的信息资产.是企业和机构核心技术骨干之一! 其实真的不是从图书管理员升级上来的.大部分是从财务管理员,以及人力资源演变过来的,起初…

OpenHarmony开发实例:【配置应用签名信息】

使用真机设备运行和调试OpenHarmony应用前&#xff0c;需要对应用进行签名才能正常运行。该指导用于OpenHarmony应用的签名配置。配置应用签名信息的流程如下图所示。 生成密钥和证书请求文件 OpenHarmony应用通过数字证书&#xff08;.cer文件&#xff09;和Profile文件&…

【华为 ICT HCIA eNSP 习题汇总】——题目集18

1、SSH默认工作使用的TCP端口号是&#xff08;&#xff09;。 A、20 B、21 C、22 D、23 考点&#xff1a;①传输层 ②应用层 解析&#xff1a;&#xff08;C&#xff09; SSH为建立在应用层和传输层上的安全协议&#xff0c;是对TCP/IP协议的传输层以上的SSH会话流程进行加密的…