1.for_each:遍历容器中的元素
void Print(int value)
{
cout << value << " ";
}
class Print1
{
public:
void operator()(int value)
{
cout << value << " ";
}
};
int main(int argc, char *argv[])
{
vector<int>v;
for(int i = 0; i < 10; i++)
{
v.push_back(i);
}
//for_each函数的第三个参数有两种实现方法,一种是普通函数,一种是仿函数
//在“stack,queue,list容器和随机访问”这篇文章最后有详细解释
for_each(v.begin(), v.end(),Print); //第一种
cout << endl;
for_each(v.begin(), v.end(),Print1()); //第二种
cout << endl;
}
2.transform:搬运容器的内容到另一个容器中,可以在函数中做修改原容器的值
void Print(int value)
{
cout << value << " ";
}
class Transform
{
public:
int operator()(int v)
{
return v;
//return v+100; 这样子就是将每个数据加上100以后再搬运
}
};
int main(int argc, char *argv[])
{
vector<int>v;
vector<int>m;
m.resize(v.size()+1); //搬运的对象必须要提前开辟空间(QT中直接v.size()搬运失败?)
for(int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), Print);
cout << endl;
transform(v.begin(),v.end(),m.begin(),Transform());
for_each(v.begin(), v.end(), Print); //两种形式,一种仿函数(类),一种普通函数
cout << endl;
}
3.常用查找算法
1.find:
find前两个参数为迭代器,最后一个为要查找的值,成功返回位置迭代器,失败返回第二个参数
查找内置数据类型时可以直接使用
vector<int>::iterator it = find(v.begin(), v.end(),5); //需要创建一个迭代器来接受返回值
if(it == v.end())
{
cout << "not found" << endl;
}
else
{
cout << "found " << (*it) << endl;
}
查找自定义数据类型的时候需要重载==
class Person
{
public:
Person(string name, int age)
{
this->name = name;
this->age = age;
}
bool operator==(const Person &p) //在类中重载==才可以使用find函数
{
if(this->name == p.name && this->age == p.age)
return true;
else
return false;
}
string name;
int age;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
vector<Person>v;
Person p1("aa",1);
Person p2("bb",2);
Person p3("cc",3);
Person p4("dd",4);
Person p5("ee",5);
Person p6("cc",3); //查找p6所代表的数据
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(),p6);
if(it == v.end())
{
cout << "not found" << endl;
}
else
{
cout << "found: name = " << it->name << "\tage = " << it->age << endl;
}
return a.exec();
}
2.find_if:
find前两个参数为迭代器,最后一个是伪函数或者函数,成功返回位置迭代器,失败返回第二个参数
查找内置数据类型:
bool fun(int value)
{
return value>8;
}
void test2()
{
vector<int>v;
for(int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>::iterator it = find_if(v.begin(), v.end(), fun);
//这里同样可以同伪函数的形式来写,重载(),返回值类型为bool
if(it == v.end())
{
cout << "not found" << endl;
}
else
{
cout << "found: " << *it << endl;
}
查找自定义数据类型
class Person
{
public:
Person(string name, int age)
{
this->name = name;
this->age = age;
}
string name;
int age;
};
bool fun1(Person &p) //这里用函数实现的条件年龄大于2,也可以使用仿函数来实现
{
return p.age>2;
}
void test1()
{
vector<Person>v;
Person p1("aa",1);
Person p2("bb",2);
Person p3("cc",3);
Person p4("dd",4);
Person p5("ee",5);
Person p6("cc",3);
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_if(v.begin(), v.end(),fun1);
if(it == v.end())
{
cout << "not found" << endl;
}
else
{
cout << "found: name = " << it->name << "\tage = " << it->age << endl;
}
}
3.adjacent_find:
查找相邻的重复元素,两个参数,前后区间的迭代器,成功返回第一个元素的迭代器,失败返回后区间的迭代器
vector<int>::iterator it = adjacent_find(v.begin(), v.end());
//开发中使用的比较少,如果有两组重复元素只能返回第一组的迭代器
4.binary_search:
查找指定的元素是否存在,存在返回true,不存在返回false;
注意这个函数只能在有序序列中使用,否则结果不准确
bool ret = binary_search(v.begin(), v.end(), 9);
5.count:
统计元素个数,参数为前后区间和元素的值
统计内置数据类型:
int num = count(v.begin(), v.end(), 9);
统计自定义数据类型:
int num = count(v.begin(), v.end(), p); //这里跟上面的find函数一样,需要在类中重载==
6.count_if与find_if形式基本相同,按条件统计元素个数
需要对比自定义数据类型的时候都要在类中重载==,因此底层的函数实现就是通过==号来识别数据的,但是自定义
的数据类型无法识别,因此需要重载,比如find和count都需要重载,但是find_if和count_if就不需要,因为它
没有通过==判断是否相等的操作,它需要判断的是大于小于,用不到==
上面的函数最后一个参数用函数或者仿函数都是可以的,形式上有点区别。
bool fun(int value) //第一种形式参数要写fun
{
return value>5;
}
class fun //第二种形式调用的时候要写fun()
{
bool operator()(int value)
{
return value>5;
}
};
4.常用排序算法
1.sort:
前两个参数为前后的迭代器,第三个参数是一个谓词,如果不填就按照从小到大的顺序进行排列
第三个参数可以用greater<int>(),变成从大到小的顺序进行排列。加上头文件#include <functional>
sort(v.begin(), v.end()); //从小到大
sort(v.begin(), v.end(),greater<int>()); //从大到小
2.random_shuffle:洗牌,打乱顺序
参数就是前后区间迭代器
加上头文件#include <ctime> 和语句 srand(unsigned int)time(NULL))让每次随机的结果都不一样
random_shuffle(v.begin(), v.end());
3.merge:
将两个有序容器中的元素合并放入另一个容器中,另一个容器依然是有序的
五个参数,两个容器的前后区间迭代器和另一个容器的前后区间迭代器
注意提前给目标容器分配空间vTarget.resize(v1.size()+v2.size());
merge(v1.gebin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
4.reserve:
两个参数前后区间迭代器
reserve(v.begin(), v.end());
5.常用拷贝和替换算法:
1.copy:完全可以用=直接赋值,没啥意义
三个参数,拷贝对象的前后区间迭代器,和目的容器的开始迭代器
注意拷贝前要先将目的容器初始化
vTarget.resize(v.size());
vTareget.copy(v.begin(), v.end(), vTarget.begin());
2.replace:
四个参数,前后区间迭代器,旧值和新值,算法是替换区间内的所有值
replace(v.begin(), v.end(), 1, 2);
3.replace_if:
满足条件的替换,四个参数,前后区间迭代器,谓词和新值。
谓词可以用仿函数或者函数的形式来写
replace_if(v.begin(), v.end(), Greater3, 4); //像这种大于3的条件,函数的返回值要写成Bool
bool Greater3(int value)
{
return value>3;
}
4.swap:
交换两个同种容器中的元素
swap(v1,v2);
5.算术生成算法:
包含的头文件是#include <numeric>
1.accumulate:计算指定区间的值的总和
三个参数,前后区间迭代器和累加的起始值
int sum = accumulate(v.gebin(), v.end(), 0);
包含的头文件是#include <numeric>
2.fill:向指定区间填充值
fill(v.begin(), v.end(), 100);
6.常用集合算法
1.set_intersection:求交集并放入另一个容器中,两个容器必须是一个有序序列
vTarget(min(v1.size(), v2.size()); //开辟空间的时候取两个容器中的较小值
vector<int>::iterator it = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
函数返回值是一个迭代器,指向最后一个有效数据,因为提前开辟的空间未必能够放满,所以遍历的时候不要用vTarget.end(),用这个函数返回的迭代器,否则出了交集外还有初始化时的默认值(0)。
2.set_union:求并集并放入另一个容器中,两个容器必须是一个有序序列
vTarget(v1.size()+v2.size()); //开辟空间的时候取两个容器的和
vector<int>::iterator it = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
函数返回值是一个迭代器,指向最后一个有效数据,因为提前开辟的空间未必能够放满,所以遍历的时候不要用vTarget.end(),用这个函数返回的迭代器,否则出了并集外还有初始化时的默认值(0)。
3.set_difference:求差集并放入另一个容器中,两个容器必须是一个有序序列
差集:v1和v2的差集就是v1中有的但是v2中没有的,顺序不同结果也是不同的
vTarget(max(v1.size(), v2.size()); //开辟空间的时候取两个容器中的较大值
vector<int>::iterator it = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
函数返回值是一个迭代器,指向最后一个有效数据,因为提前开辟的空间未必能够放满,所以遍历的时候不要用vTarget.end(),用这个函数返回的迭代器,否则出了交集外还有初始化时的默认值(0)。