1.容器算法
1.1 算法概述
算法主要是由头文件<algorithm><functional><numeric>组成。
1.<algorithm>是所有STL头文件中最大的一个,其中常用的功能涉及到比较,交换,查找,
遍历,复制,修改,反转,排序,合并等...
2.<numeric>体积很小,只包括在几个序列容器上进行的简单运算的模板函数.
3.<functional> 定义了一些模板类,用以声明函数对象。
1.2 常用遍历算法
1. for_each遍历算法 遍历容器元素
@param beg 开始迭代器
@param end 结束迭代器
@param _callback 函数回调或者函数对象
@return 函数对象
for_each(iterator beg, iterator end, _callback);
2.transform算法 将指定容器区间元素搬运到另一容器中
注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
@param beg1 源容器开始迭代器
@param end1 源容器结束迭代器
@param beg2 目标容器开始迭代器
@param _cakkback 回调函数或者函数对象
@return 返回目标容器迭代器
源码:
template<class _InIt,class _Fn1> inline
void for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{
for (; _First != _Last; ++_First)
_Func(*_First);
}
transform(iterator beg1, iterator end1, iterator beg2, _callbakc)
源码:
template<class _InIt, class _OutIt, class _Fn1> inline
_OutIt _Transform(_InIt _First, _InIt _Last,_OutIt _Dest, _Fn1 _Func)
{
for (; _First != _Last; ++_First, ++_Dest)
*_Dest = _Func(*_First);
return (_Dest);
}
template<class _InIt1,class _InIt2,class _OutIt,class _Fn2> inline
_OutIt _Transform(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
{
for (; _First1 != _Last1; ++_First1, ++_First2, ++_Dest)
*_Dest = _Func(*_First1, *_First2);
return (_Dest);
}
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
void myPrint(int a)
{
cout << a << " ";
}
struct MyAdd
{
int operator()(int val)
{
return val + 100;
}
};
struct MyAdd1
{
int operator()(int val1,int val2)
{
return val1 + val2;
}
};
struct MyPrint
{
public:
MyPrint()
{
a = 0;
}
void operator()(const int &val)
{
cout << val << " ";
++a;
}
int a;
};
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);
MyPrint m = for_each(v.begin(), v.end(), MyPrint());
cout << endl;
cout << m.a << endl;
}
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);
vector<int> v2;
v2.resize(v.size());
transform(v.begin(), v.end(), v2.begin(), MyAdd());
for_each(v2.begin(), v2.end(), MyPrint());
}
void test03()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
vector<int> v2;
v2.push_back(11);
v2.push_back(22);
v2.push_back(33);
v2.push_back(44);
v2.push_back(55);
vector<int> v3;
if (v.size() > v2.size())
{
v3.resize(v.size());
}
else
{
v3.resize(v2.size());
}
transform(v.begin(), v.end(), v2.begin(),v3.begin(), MyAdd1());
for_each(v3.begin(), v3.end(), MyPrint());
}
int main()
{
test03();
system("pause");
return 0;
}
1.3 常用查找算法
1.find算法 查找元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return 返回查找元素的位置
find(iterator beg, iterator end, value)
2.adjacent_find算法 查找相邻重复元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param _callback 回调函数或者谓词(返回bool类型的函数对象)
@return 返回相邻元素的第一个位置的迭代器
adjacent_find(iterator beg, iterator end, _callback);
3.binary_search算法 二分查找法
注意: 在无序序列中不可用
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return bool 查找返回true 否则false
bool binary_search(iterator beg, iterator end, value);
4.find_if算法 条件查找
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 回调函数或者谓词(返回bool类型的函数对象)
@return bool 查找返回true 否则false
find_if(iterator beg, iterator end, _callback);
5.count算法 统计元素出现次数
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value回调函数或者谓词(返回bool类型的函数对象)
@return int返回元素个数
count(iterator beg, iterator end, value);
count算法 统计元素出现次数
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 回调函数或者谓词(返回bool类型的函数对象)
@return int返回元素个数
6.count_if(iterator beg, iterator end, _callback);
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
bool myBool(int val)
{
return val > 30;
}
class Student
{
public:
Student(string name, int age)
{
this->age = age;
this->name = name;
}
bool operator==(const Student& s)
{
return ((this->age == s.age) && (this->name == s.name));
}
string name;
int age;
};
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);
vector<int>::iterator it = find(v.begin(), v.end(), 20);
if (it == v.end())
cout << "查找失败!" << endl;
else
cout << "查找成功! " << *it << endl;
it = find_if(v.begin(), v.end(), myBool);
if (it == v.end())
cout << "查找失败!" << endl;
else
cout << "查找成功! " << *it << endl;
}
struct MyFind:public binary_function<Student,Student,bool>
{
bool operator()(Student s1,Student s2) const
{
return s1.name == s2.name && s1.age == s2.age;
}
};
void test02()
{
vector<Student> v;
v.push_back(Student("aaa",18));
v.push_back(Student("vvv",19));
v.push_back(Student("eee",17));
v.push_back(Student("ddd",21));
v.push_back(Student("ccc",20));
vector<Student>::iterator it = find(v.begin(), v.end(), Student("eee", 17));
if (it == v.end())
cout << "查找失败!" << endl;
else
cout << "查找成功! " << (*it).age <<" "<<(*it).name << endl;
it = find_if(v.begin(), v.end(), bind2nd(MyFind(), Student("eee", 17)));
if (it == v.end())
cout << "查找失败!" << endl;
else
cout << "查找成功! " << (*it).age << " " << (*it).name << endl;
}
bool myAdj_find(Student &s1,Student &s2)
{
return s1.name == s2.name && s1.age == s2.age;
}
void test03()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);
vector<int>::iterator it = adjacent_find(v.begin(), v.end());
if (it == v.end())
cout << "查找相邻的重复元素失败!" << endl;
else
cout << "查找成功! " << *it << endl;
vector<Student> v1;
v1.push_back(Student("aaa", 18));
v1.push_back(Student("vvv", 19));
v1.push_back(Student("vvv", 19));
v1.push_back(Student("ddd", 21));
v1.push_back(Student("ccc", 20));
vector<Student>::iterator sit = adjacent_find(v1.begin(), v1.end(), myAdj_find);
if (sit == v1.end())
cout << "查找相邻的重复元素失败!" << endl;
else
cout << "查找成功! " << sit->name <<" "<<sit->age << endl;
}
class Student1
{
public:
Student1(string name, int age)
{
this->age = age;
this->name = name;
}
bool operator>(const Student1& s) const
{
return this->age > s.age;
}
bool operator<(const Student1& s) const
{
return this->age < s.age;
}
string name;
int age;
};
bool MyBinary_Search(const Student& s1, const Student& s2)
{
return ((s1.age == s2.age) && (s1.name == s2.name));
}
void test04()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(80);
v.push_back(40);
v.push_back(50);
bool flag = binary_search(v.begin(), v.end(), 40);
if (flag)
{
cout << "查找成功!" << endl;
}
else
cout << "查找失败!" << endl;
vector<Student1> v1;
v1.push_back(Student1("aaa", 18));
v1.push_back(Student1("vvv", 19));
v1.push_back(Student1("vvv", 20));
v1.push_back(Student1("ddd", 21));
v1.push_back(Student1("ccc", 22));
bool flag1 = binary_search(v1.begin(), v1.end(), Student1("ddd", 21));
if (flag1)
{
cout << "查找成功!" << endl;
}
else
cout << "查找失败!" << endl;
}
bool MyCount(int val)
{
return val > 10;
}
void test05()
{
vector<int> v;
v.push_back(10);
v.push_back(10);
v.push_back(20);
v.push_back(20);
v.push_back(20);
v.push_back(30);
v.push_back(40);
int m_cout = count(v.begin(), v.end(), 20);
cout << m_cout << endl;
int m_cout1 = count_if(v.begin(), v.end(), MyCount);
cout << m_cout1 << endl;
vector<Student> v1;
v1.push_back(Student("aaa", 18));
v1.push_back(Student("vvv", 19));
v1.push_back(Student("vvv", 19));
v1.push_back(Student("vvv", 19));
v1.push_back(Student("ccc", 22));
int m_cout2 = count(v1.begin(), v1.end(), Student("vvv", 19));
cout << m_cout2 << endl;
}
int main()
{
test05();
system("pause");
return 0;
}
1.4 常用排序算法
1.merge算法 容器元素合并,并存储到另一容器中
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
2.sort算法 容器元素排序
注意:两个容器必须是有序的
@param beg 容器1开始迭代器
@param end 容器1结束迭代器
@param _callback 回调函数或者谓词(返回bool类型的函数对象)
sort(iterator beg, iterator end, _callback)
3.random_shuffle算法 对指定范围内的元素随机调整次序
@param beg 容器开始迭代器
@param end 容器结束迭代器
random_shuffle(iterator beg, iterator end)
4.reverse算法 反转指定范围的元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
reverse(iterator beg, iterator end)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include<ctime>
using namespace std;
struct MySort
{
public:
bool operator()(int a1, int a2)
{
return a1 > a2;
}
};
void test01()
{
vector<int> v1;
vector<int> v2;
for (int i = 0; i < 5; i++)
{
v1.push_back(i+10);
v2.push_back(i+1);
}
vector<int> v3;
v3.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin(),greater<int>());
for_each(v3.begin(), v3.end(), [](int val) {cout << val << " "; });
}
void test02()
{
vector<int> v1;
v1.push_back(10);
v1.push_back(11);
v1.push_back(15);
v1.push_back(14);
v1.push_back(12);
sort(v1.begin(), v1.end(), MySort());
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
}
void test03()
{
vector<int> v1;
for (int i = 0; i < 5; i++)
{
v1.push_back(i + 10);
}
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
random_shuffle(v1.begin(), v1.end());
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
}
void test04()
{
vector<int> v1;
for (int i = 0; i < 5; i++)
{
v1.push_back(i + 10);
}
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
reverse(v1.begin(), v1.end());
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
}
int main()
{
srand((unsigned int)time(NULL));
test04();
system("pause");
return 0;
}
1.5 常用拷贝和替换算法
1.copy算法 将容器内指定范围的元素拷贝到另一容器中
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param dest 目标容器结束迭代器
copy(iterator beg, iterator end, iterator dest)
2.replace算法 将容器内指定范围的旧元素修改为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param oldvalue 旧元素
@param oldvalue 新元素
replace(iterator beg, iterator end, oldvalue, newvalue)
3.replace_if算法 将容器内指定范围满足条件的元素替换为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback函数回调或者谓词(返回Bool类型的函数对象)
@param oldvalue 新元素
replace_if(iterator beg, iterator end, _callback, newvalue)
4.swap算法 互换两个容器的元素
@param c1容器1
@param c2容器2
swap(container c1, container c2)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include<ctime>
using namespace std;
void test01()
{
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
vector<int> v2;
v2.resize(v1.size());
copy(v1.begin(), v1.end(), v2.begin());
for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });
}
bool Myreplace(int v1)
{
return v1 > 20;
}
void test02()
{
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
replace(v1.begin(), v1.end(), 20, 200);
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
replace_if(v1.begin(), v1.end(), Myreplace, 666);
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
}
void test03()
{
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
vector<int> v2;
v2.push_back(1);
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
v2.push_back(5);
swap(v1, v2);
for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });
cout << endl;
for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });
cout << endl;
}
int main()
{
test03();
system("pause");
return 0;
}
1.6 常用算数生成算法
1.accumulate算法 计算容器元素累计总和
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value累加值
accumulate(iterator beg, iterator end, value)
2.fill算法 向容器中添加元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value t填充元素
fill(iterator beg, iterator end, value)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include<numeric>
using namespace std;
class Student
{
public:
Student(string name, int age)
{
this->name = name;
this->age = age;
}
string name;
int age;
};
struct MyPlus
{
public:
int operator()(int val,Student& s)
{
return val + s.age;
}
};
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
int ret = accumulate(v.begin(), v.end(), 0);
cout << ret << endl;
vector<Student> v1;
v1.push_back(Student("aaa", 18));
v1.push_back(Student("bbb", 19));
v1.push_back(Student("ccc", 21));
int ret1 = accumulate(v1.begin(), v1.end(),0, MyPlus());
cout << ret1 << endl;
}
void test02()
{
vector<int> v;
v.resize(10);
fill(v.begin(), v.end(), 100);
for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });
cout << endl;
}
int main()
{
test02();
system("pause");
return 0;
}
1.7 常用集合算法
1.set_intersection算法 求两个set集合的交集
注意:两个集合必须是有序序列
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
2.set_union算法 求两个set集合的并集
注意:两个集合必须是有序序列
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
3.set_difference算法 求两个set集合的差集
注意:两个集合必须是有序序列
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
void test01()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int> v1;
for (int i = 0; i < 15; i++)
{
v1.push_back(i);
}
vector<int> v2;
v2.resize(min(v.size(),v1.size()));
set_intersection(v.begin(), v.end(), v1.begin(), v1.end(), v2.begin());
for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });
cout << endl;
}
void test02()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int> v1;
for (int i = 0; i < 15; i++)
{
v1.push_back(i);
}
vector<int> v2;
v2.resize(v.size()+v1.size());
set_union(v.begin(), v.end(), v1.begin(), v1.end(), v2.begin());
for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });
cout << endl;
}
void test03()
{
vector<int> v;
for (int i = 1; i < 6; i++)
{
v.push_back(i);
}
vector<int> v1;
for (int i = 2; i < 7; i++)
{
v1.push_back(i);
}
vector<int> v2;
v2.resize(v.size() + v1.size());
set_difference(v.begin(), v.end(), v1.begin(), v1.end(), v2.begin());
for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });
cout << endl;
}
int main()
{
test03();
system("pause");
return 0;
}
2. 案例:
2.1 歌唱比赛,共24人参赛分为三组,每组6人,每轮淘汰三名选手,共10个评委打分,去掉
最高分和最低分后取平均就是该选手在当前轮的成绩。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<deque>
#include<map>
#include<ctime>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
#define PARTERNUM 24
class Parter
{
public:
string name;
int age;
int score[3];
};
void creatParter(vector<int>& v, map<int, Parter>& m1)
{
string p_Name = "ABCDEFGHIJKLMNOPQRSTUVWX";
for (int i = 0; i < PARTERNUM; i++)
{
v.push_back(i+1);
Parter p;
p.age = rand() % 8 + 16;
for (int j = 0; j < 3; j++)
{
p.score[j] = 0;
}
p.name = "选手";
p.name += p_Name[i];
m1.insert(pair<int, Parter>(i+1, p));
}
}
void parterRandom(vector<int>& v)
{
random_shuffle(v.begin(), v.end());
}
void startParter(int num, vector<int>& v1, map<int, Parter>& m1, vector<int>& v2)
{
multimap<int, int,greater<int>> tempm;
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{
deque<int> d;
for (int i = 0; i < 10; i++)
{
int score = rand() % 70 + 30;
d.push_back(score);
}
sort(d.begin(), d.end());
d.pop_back();
d.pop_front();
int sum = accumulate(d.begin(),d.end(),0);
sum /= d.size();
m1[*it].score[num - 1] = sum;
tempm.insert(pair<int, int>(sum, *it));
if (tempm.size() == 6)
{
int count_num = 0;
for (multimap<int, int, greater<int>>::iterator mit = tempm.begin();mit != tempm.end() && count_num < 3; mit++, count_num++)
{
v2.push_back(mit->second);
}
tempm.clear();
}
}
}
void showParter(int num, vector<int>& v1, map<int, Parter>& m1)
{
cout << "第" << num << "轮比赛晋级选手名单:" << endl;
for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{
cout << "\t选手姓名:" << m1[*it].name << " 选手年龄:" << m1[*it].age << " 选手分数:";
for (int j = 0; j < num; j++)
{
cout << m1[*it].score[j]<<" ";
}
cout << endl;
}
}
void test()
{
srand((unsigned int)time(NULL));
vector<int> v;
map<int, Parter> m1;
vector<int> v1;
vector<int> v2;
vector<int> v3;
creatParter(v, m1);
parterRandom(v);
startParter(1,v,m1,v1);
showParter(1, v1,m1);
parterRandom(v1);
startParter(2, v1, m1, v2);
showParter(2, v2, m1);
parterRandom(v2);
startParter(3, v2, m1, v3);
showParter(3, v3, m1);
}
int main()
{
test();
system("pause");
return 0;
}