C++之常用的算法
C++之常用的算法
1 函数对象
重载函数调用运算符的类,其对象称为函数对象。 一元仿函数 / 二元仿函数(根据参数个数判定)class MyPrint {
public:
void operator() (int num) {
cout << "num = " << num << endl;
}
};
void test01() {
MyPrint myPrint;
myPrint(2); // 仿函数的调用
}
class MyPrint {
public:
MyPrint() {
count = 0;
}
void operator() (int num) {
count++;
cout << "num = " << num << endl;
}
int count;
};
// 函数对象超出了普通函数的概念 可以保存状态
void test02() {
MyPrint myPrint;
myPrint(1);
myPrint(10);
myPrint(10);
myPrint(10);
myPrint(10);
cout << "调用函数对象"<< myPrint.count << "次"<<endl;
}
// 函数对象作为参数传递
void doPrint(MyPrint print,int num) {
print(num);
}
void test03() {
MyPrint myPrint;
doPrint(myPrint,19);
}
总结: 函数对象(仿函数)重载了(),所以就像函数的调用。作为类型与模板配合使用。
set<int,myCompare>
2 谓词
普通函数或返回值是bool值的函数对象(operator()),
class Greater20 {
public:
bool operator()(int val) {
return val > 20;
}
};
// 一元谓词
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
// 查大于20的数
Greater20 greater20Then;
vector<int>::iterator pos = find_if(v.begin(),v.end(), greater20Then);
if (pos != v.end()) {
cout << "找到大于20的位置="<< *pos << endl;
}
else {
cout << "未找到" << endl;
}
}
// 二元谓词
class MyCompare{
public:
bool operator()(int v1,int v2) {
return v1 > v2;
}
};
void test02() {
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
sort(v.begin(),v.end(), MyCompare());
// 匿名函数 lambda表达式 [](){};
for_each(v.begin(), v.end(), [](int val) {
cout << val << " ";
});
cout << endl;
}
3 内建函数对象的使用
#include <functional>
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <functional>
#include <vector>
#include <algorithm>
void test01() {
// 取反仿函数
// template<class T> T negate<T>
negate<int> n;
cout <<n(10) << endl;
// 加法
// template<class T> T plus<T>
plus<int> p;
cout << p(1, 1) << endl;
}
// template<class T> bool greater<T>
void test02() {
vector<int> v;
v.push_back(10);
v.push_back(11);
v.push_back(12);
v.push_back(9);
v.push_back(6);
sort(v.begin(),v.end(),greater<int>());
for (int a : v) {
cout << a << " ";
}
}
int main()
{
test02();
system("pause");
return EXIT_SUCCESS;
}
4 适配器
函数适配器
// 第一步 绑定数据
// 第二步 继承类binary_function<参数类型1,参数类型2,返回值类型>
// 第三步 加const修饰 operator()
class MyPrint : public binary_function<int,int,void>
{
public:
void operator() (int v,int start) const // 常函数
{
cout << "v=" << v << " start=" << start << " v+start=" << v + start << endl;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 10;i++) {
v.push_back(i);
}
cout << "请输入一个起始值:" << endl;
int num;
cin >> num;
// 引入头文件 functional algorithm
for_each(v.begin(),v.end(), bind2nd(MyPrint(),num));
//for_each(v.begin(), v.end(), bind1st(MyPrint(), num));
}
class greater5 :public unary_function<int,bool>
{
public :
bool operator()(int v) const
{
return v > 5;
}
};
// 取反适配器
void test02() {
// 一元取反
vector<int> v;
for (int i = 0; i < 10;i++) {
v.push_back(i);
}
// 查找大于5的数字
vector<int>::iterator pos = find_if(v.begin(),v.end(), not1(greater5())); // 一元取反
if (pos != v.end()) {
cout << "找到小于5的数字" << *pos << endl;
}
}
vector<int>::iterator pos = find_if(v.begin(), v.end(), not1( bind2nd(greater<int>(),5)));
void myPrint(int v,int start) {
cout << v << " ";
}
// 函数指针适配器
void test03() {
vector<int> v;
for (int i = 0; i < 10;i++) {
v.push_back(i );
}
// 将函数指针 适配为函数对象
for_each(v.begin(),v.end(),bind2nd(ptr_fun(myPrint),5));
cout << "\n";
}
// 成员函数适配器
class Person {
public:
Person(string name, int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
void myPrintPerson(Person &p) {
cout << "姓名:" << p.m_name << "\t年龄:" << p.m_age << endl;
}
void test04() {
vector<Person> v;
Person p1("张三",13);
Person p2("李四", 23);
Person p3("王五", 33);
Person p4("赵六", 43);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
for_each(v.begin(),v.end(), myPrintPerson);
}
// 成员函数的适配器
// mem_fun_ref
for_each(v.begin(), v.end(),mem_fun_ref(&Person::showPerson));
5 常用遍历算法
第一个是for_each
使用for_each需要导入
两个作用:1.可以保存状态, 2. 可以绑定参数进行输出
struct MyPrint { // struct内部默认就是public
void operator()(int v) {
cout << v << " ";
m_Count++;
}
int m_Count=0;
};
void test01() {
vector<int> v;
for (int i = 0; i < 10;i++) {
v.push_back(i);
}
//for_each(v.begin(),v.end(), showV);
MyPrint print = for_each(v.begin(), v.end(), MyPrint());
cout << "累计次数="<< print.m_Count << endl;
cout << endl;
}
transform算法,将指定容器中的元素搬运到另外一个容器中。
void test04() {
vector<int> v; // 原容器
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int> target;
//target.reserve(v.size());
target.resize(v.size());
transform(v.begin(),v.end(),target.begin(), Transform());
for_each(target.begin(), target.end(), [](int val) {
cout << val << " ";
});
}
// transform的第二种用法: 将两个容器元素搬运到目标元素中
class Transform2 {
public:
int operator()(int val,int val2) {
return val + val2;
}
};
void test05() {
vector<int> v1;
vector<int> v2;
for (int i = 0; i < 10;i++) {
v1.push_back(i+100); // 100 101 102 103
v2.push_back(i+10); // 10 11 12 13
}
vector<int> vtarget;
vtarget.resize(v1.size());
transform(v1.begin(),v1.end(),v2.begin(),vtarget.begin(),Transform2());
for_each(vtarget.begin(), vtarget.end(), [](int val) {
cout << val << " ";
});
cout << endl;
}
6 常用的查找算法
使用find()查找SLT容器中的元素。
void test() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int>::iterator ele = find(v.begin(),v.end(),5);
if (ele != v.end()) {
cout << "找到\n";
}
else {
cout << "未找到\n";
}
}
查找自定义的数据类型
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include <string >
void test() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int>::iterator ele = find(v.begin(),v.end(),5);
if (ele != v.end()) {
cout << "找到\n";
}
else {
cout << "未找到\n";
}
}
class Person {
public:
Person(string name, int age) {
this->m_Name = name;
this->age = age;
}
bool operator==(const Person &p) {
if (this->m_Name == p.m_Name && this->age == p.age) {
return true;
}
else {
return false;
}
}
string m_Name;
int age;
};
// 使用find函数查找自定义类型数据
void test02() {
vector<Person> p;
Person p1("Alice",12);
Person p2("Bob",21);
Person p3("Kili",23);
p.push_back(p1);
p.push_back(p2);
p.push_back(p3);
vector<Person>::iterator pos = find(p.begin(),p.end(),p2);
if (pos != p.end()) {
cout << pos->m_Name << " " << pos->age << endl;
}
else{
cout << "没有找到" << endl;
}
}
int main()
{
test02();
system("pause");
return EXIT_SUCCESS;
}
// 查找指针类型的数据
class MyCompare:public binary_function<Person *, Person *,bool>
{
public:
bool operator()( Person * p1, Person * p2) const
{
if (p1->m_Name == p2->m_Name && p1->age == p2->age) {
return true;
}
else return false;
}
};
void test03() {
vector<Person *> p;
Person p1("Alice", 12);
Person p2("Bob", 21);
Person p3("Kili", 23);
p.push_back(&p1);
p.push_back(&p2);
p.push_back(&p3);
vector<Person *>::iterator pos = find_if(p.begin(),p.end(), bind2nd(MyCompare(),&p1));
if (pos != p.end() ) {
cout << "找到:" <<(*pos)->m_Name<<"->"<<(*pos)->age<< endl;
}
else {
cout << "未找到" << endl;
}
}
/*
adjacent_find 算法 查找相邻重复元素
beg 容器开始迭代器
end 容器结束迭代器
_callback 回调函数 或者谓词
*/
void test04()
{
vector<int> v;
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(5);
v.push_back(6);
v.push_back(7);
vector<int>::iterator pos = adjacent_find(v.begin(), v.end());
if (pos !=v.end()) {
cout << "找到" <<*pos << endl; // 5
}
else {
cout << "找到相邻的元素" << endl;
}
}
/*
binary_search 二分查找
*/
void test05()
{
vector<int> v;
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(5);
v.push_back(6);
v.push_back(7);
bool res = binary_search (v.begin(), v.end(),5);
if (res) {
cout << "找到" << endl;
}
else {
cout << "没找到" << endl;
}
}
// count 统计元素的个数
// count_if
class Greate4 {
public:
bool operator()(int val) {
return val > 4;
}
};
void test06()
{
vector<int> v;
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(5);
v.push_back(6);
v.push_back(7);
int nums = count(v.begin(),v.end(),5);
cout << nums << endl;
int num = count_if(v.begin(),v.end(), Greate4()); // 输出大于4个元素个数
cout << num << endl;
}
7 常用的排序算法
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <functional>
#include <ctime>
/*
merge算法: 容器元素合并,将两个容器并存储到另外一个容器中,两个容器元素必须是有序的
*/
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> vTaregt;
vTaregt.resize(v1.size()+v2.size());
merge(v1.begin(),v1.end(),v2.begin(),v2.end(),vTaregt.begin());
for_each(vTaregt.begin(), vTaregt.end(), [](int v) {cout << v << " "; });
}
/*
sort 算法
*/
void test02() {
vector<int> v1;
v1.push_back(2);
v1.push_back(1);
v1.push_back(9);
v1.push_back(3);
v1.push_back(11);
sort(v1.begin(),v1.end());
for_each(v1.begin(), v1.end(), [](int v) { cout << v << " "; });
sort(v1.begin(), v1.end(),greater<int>());
cout << endl;
for_each(v1.begin(), v1.end(), [](int v) { cout << v << " "; });
}
// random_shuffle(iterator beg,iterator end)算法 洗牌算法
void test03() {
srand( (unsigned int)time(NULL));
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(), [](int v) { cout << v << " "; });
cout << endl;
// reverse 将容器中的元素翻转
reverse(v.begin(),v.end());
for_each(v.begin(), v.end(), [](int v) { cout << v << " "; });
cout << endl;
}
int main()
{
//test01();
//test02();
test03();
system("pause");
return EXIT_SUCCESS;
}
合并算法(merge) / 排序算法
8 常用的拷贝和替换算法
//copy 算法 将一个容器中的元素 拷贝到另外一个容器中
void test01() {
vector<int> v;
for (int i = 0; i < 10;i++) {
v.push_back(i);
}
vector<int> v1;
v1.resize(v.size());
copy(v.begin(),v.end(),v1.begin());
for_each(v1.begin(), v1.end(), [](int v) { cout << v << " "; });
cout << endl;
}
// replace
// replace_if
void test02() {
vector<int> v;
for (int i = 0; i < 4;i++) {
v.push_back(i);
}
// 将容器中的3替换成300
replace(v.begin(),v.end(),3,300);
for_each(v.begin(), v.end(), [](int v) { cout << v << " "; });
}
// swap 算法 交换容器中的两个元素
void test03() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
vector<int> v2;
v2.push_back(10);
v2.push_back(20);
v2.push_back(30);
v2.push_back(40);
cout << "交换前的数据:" << endl;
for_each(v1.begin(), v1.end(), [](int v) { cout << v << " "; });
cout << endl;
cout << "交换后的数据" << endl;
swap(v1,v2);
for_each(v1.begin(), v1.end(), [](int v) { cout << v << " "; });
cout << endl;
for_each(v2.begin(), v2.end(), [](int v) { cout << v << " "; });
cout << endl;
}
9 常用的算数生成算法
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <vector>
#include <numeric>
#include <iterator>
// accumulate 累加 计算容器元素的累加和
void test01() {
vector<int> v;
for (int i = 0; i < 10;i++) {
v.push_back(i);
}
// 计算累计和
int res = accumulate(v.begin(),v.end(),10);
cout << res << endl;
}
// fill 向容器中添加元素
void test02() {
vector <int> v;
v.resize(10); // 初始化 10个0
fill(v.begin(),v.end(),1000); // 填充1000
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
}
int main()
{
test02();
system("pause");
return EXIT_SUCCESS;
10 常用的集合算法(一般用不到)
交集、并集、差集
/*
set_intersection算法,求两个集合的交集
*/
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 end = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
//for_each(vTarget.begin(), vTarget.end(), [](int v) {
// cout << v << " ";
//});
copy(vTarget.begin(), end, ostream_iterator<int>(cout," ")); // 5 6 7 8 9
}
// 并集
// set_union
void test02() {
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 end = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
//for_each(vTarget.begin(), vTarget.end(), [](int v) {
// cout << v << " ";
//});
copy(vTarget.begin(), end, ostream_iterator<int>(cout, " ")); // 0-14
}
// 差集
void test03() {
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());
// v1-v2
vector<int>::iterator end = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
//for_each(vTarget.begin(), vTarget.end(), [](int v) {
// cout << v << " ";
//});
copy(vTarget.begin(), end, ostream_iterator<int>(cout, " ")); // 0-14
}