# STL的基本算法

#include <iostream>
#include<functional>
#include<list>
#include<vector>
#include<set>
#include<iterator>
#include<algorithm>
#include<memory>
using namespace std;

template<class T>
void Print(const T& t,char *str="")
{
cout << str;
//获得t模板的类型，如t为vector<int>,则value_type为int
typedef typename iterator_traits<T::iterator>::value_type value_type;
for_each(t.begin(), t.end(), [](value_type _t) {cout << _t << " , "; });
cout << endl;
}
//查找算法
void FindAlgorithm()
{
int num[] = { 1,2,2,3,3,3,4,4,4,4 };
vector<int> v;
v.assign(num, num + 10);
Print(v);
auto pos = find(v.begin(), v.end(), 4); //返回第一个找到的iterator，如果找不到则返回end()
cout << "第一个4的位置" << distance(v.begin(), pos) + 1 << endl;//7

auto pos2 = find_if(v.begin(), v.end(), bind2nd(greater<int>(), 3));
cout << "第一个大于3的位置" << distance(v.begin(), pos2) + 1 << endl;//7

auto pos3 = search_n(v.begin(), v.end(), 3, 3);
cout << "3个3的位置" << distance(v.begin(), pos3) + 1 << endl;//4

auto pos4 = search_n(v.begin(), v.end(), 4, 3, greater<int>());
cout << "4个大于3的位置" << distance(v.begin(), pos4) + 1 << endl;//7

int subnum[] = { 3,3,4 };
auto pos5 = search(v.begin(), v.end(), subnum, subnum + 3);
cout << "子串位置" << distance(v.begin(), pos5) + 1 << endl;

auto pos6 = search(v.begin(), v.end(), subnum, subnum + 3, [](int a, int b) {return a == b - 1; });
cout << "子串减一后匹配原串的位置，此处即匹配[2，2，3] " << distance(v.begin(), pos6) + 1 << endl;//2

cout << "第一个有两个连续相等的元素位置" << distance(v.begin(), pos7) + 1 << endl;//2

auto pos8 = adjacent_find(v.begin(), v.end(), [](int left, int right) {return left * 2 == right; });
cout << "第一个有两个连续元素左边为右边为两倍的位置" << distance(v.begin(), pos8) + 1 << endl; //1
}
//比较算法
void CompareAlgorithm()
{
int num[] = { 1,2,3,4,5 };
int num2[] = { 2,3,4,5,6 };
vector<int>v1, v2;
v1.assign(num, num + 5);
v2.assign(num2, num2 + 5);
bool b1 = equal(v1.begin(), v1.end(), v2.begin());
bool b2 = equal(v1.begin(), v1.end(), v2.begin(), [](int left, int right) {return left + 1 == right; });
cout << b1 << "," << b2 << endl; //输出为0，1

//p1返回v1,v2不同元素的迭代器组成的pair,若v1,v2相同，则 p1.first == v1.end()
auto p1 = mismatch(v1.begin(), v1.end(), v2.begin());
cout << *p1.first << " , " << *p1.second << endl; //输出1，2
auto p2 = mismatch(v1.begin(), v1.end(), v2.begin(), [](int left, int right) {return left * 2 == right; });
cout << *p2.first << " , " << *p2.second << endl;//输出2，3 因为num[0] * 2 == num2[0],而num[1]*2 != num2[1]

cout << lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end());//默认比较v1是否小于v2
}
//拷贝算法
void CopyAlgorithm()
{
int num[] = { 1,2,3,4,5 };
vector<int>v;
v.assign(num, num + 5);
list<int>L1;
/*copy(v.begin(), v.end(), ostream_iterator<int>(cout, ","));
cout << endl;*/
copy(v.begin(), v.end(), back_inserter(L1));//使用插入型迭代器，此时L1为1，2，3，4，5
Print(L1);

//将 2,3拷贝到v的最后面,此时L1为1，2，3，2，3
copy_backward(v.begin() + 1, v.begin() + 3, L1.end());
Print(L1);

//将v中的偶数拷贝到L1开头，此时L1为2，4，3，2，3
copy_if(v.begin(), v.end(), L1.begin(), [](int t) {return t % 2 == 0; });
Print(L1);

//在拷贝过程中删除一些元素，此例删除3，即将v中的3删掉，剩余元素拷贝到L1开头，此时L1为1，2，4，5，3
remove_copy(v.begin(), v.end(), L1.begin(), 3);
Print(L1);

//在拷贝过程中删除偶数，此时L1为 1,3,5,5,3
remove_copy_if(v.begin(), v.end(), L1.begin(), [](int t) {return t % 2 == 0; });
Print(L1);
}
//转换算法,将转换与拷贝集合到一起
void TransformAlgorithm()
{
int num[] = { 1,2,3,4,5 };
vector<int>v;
v.assign(num, num + 5);
list<int>L;
//将v中的元素分别乘-1后插入到L中
transform(v.begin(), v.end(), back_inserter(L), negate<int>());
Print(L);

//将v中的元素分别乘10后插入到L的开头
//plus<int>() ,divides<int>()  ,minus<int>()
transform(v.begin(), v.end(), L.begin(), bind2nd(multiplies<int>(), 10));
Print(L);

//将v*v拷贝到L开头
transform(v.begin(), v.end(), v.begin(), L.begin(), multiplies<int>());
Print(L);

//使用自定义函数

//template<class T>
//class customFunc
//{
//public:
//	customFunc(const T & t) :value(t) {}
//	int operator()(const T &t)const
//	{
//		return t * value;
//	}
//private:
//	T value;
//};
//template<class T>
//class customFunc2
//{
//public:
//	customFunc2(const T & t) :value(t) {}
//	int operator()(const T &t1, const T&t2)const
//	{
//		return (t1 + t2)*value;
//	}
//private:
//	T value;
//};

////将v中的元素分别乘3后插入到L中
//等价于transform(v.begin(), v.end(), back_inserter(L), [](int t) {return t * 3; });
//transform(v.begin(), v.end(), back_inserter(L), customFunc<int>(3));

//Print(L);
////将v中的元素分别加上L的元素再乘2，最后拷贝到L的起始位置处
//transform(v.begin(), v.end(), L.begin(), L.begin(), customFunc2<int>(2));
//Print(L);
}
//交换算法
void SwapAlgorithm()
{
int num[] = { 1,2,3,4,5 };
vector<int>v;
v.assign(num, num + 5);
vector<int>L;
transform(v.begin(), v.end(), back_inserter(L), [](int t) {return t + 10; });
Print(L);//11,12,13,14,15
swap_ranges(v.begin(), v.begin() + 3, L.begin());
Print(v, "v:");//11 12 13 4 5
Print(L, "L:");//1,2,3,14,15

//swap(v, L);
}
//赋值算法
void AssignAlgorithm()
{
int num[] = { 1,2,3,4,5,6,7,8,9 };
vector<int>v;
v.assign(num, num + 9);
//将v的前4个元素赋值为10
fill(v.begin(), v.begin() + 4, 10);
Print(v);
//从begin位置开始的3个数赋值为20
fill_n(v.begin(), 3, 20);
Print(v);

//generate(v.begin(), v.end(), rand);
//Print(v);
//生成4个随机数拷贝到v.begin 开始的4个位置处
generate_n(v.begin(), 4, rand);
Print(v);
}
//替换算法
void ReplaceAlgorithm()
{
int num[] = { 1,2,4,4,5,6,7,8,9 };
vector<int>v;
v.assign(num, num + 9);
//将所有的4换成5
replace(v.begin(), v.end(), 4, 5);
Print(v);
//将所有大于5的数换成0
replace_if(v.begin(), v.end(), bind2nd(greater<int>(), 5), 0);
Print(v);
}
//翻转算法
void ReverseAlgorithm()
{
int num[] = { 1,2,4,4,5,6,7,8,9 };
vector<int>v;
list<int>L;
v.assign(num, num + 9);
L.assign(num, num + 9);

auto posL = L.begin();
auto posR = L.end();
reverse(v.begin() + 2, v.end() - 2);
reverse(posL, posR);//翻转L的第3-7个元素
Print(L, "L:");//1,2,,7,6,5,4,3,8,9
Print(v, "v:");

vector<int>v2;
reverse_copy(v.begin(), v.end(), back_inserter(v2));//将v翻转后拷贝到v2中
Print(v2);
}
//排列算法
void ShuffleAlgorithm()
{
int num[] = { 1,2,3,4,5,6,7,8,9 };
vector<int>v;
list<int>L;
v.assign(num, num + 9);
L.assign(num, num + 9);

random_shuffle(v.begin(), v.begin() + 5);//随机重排，遵循均匀分布。也可跟第三个参数，给出一个仿函数
Print(v);

//while (next_permutation(v.begin(), v.end(), [](int a,int b) {return a > b; }));//降序
Print(v);
}
//排序算法
void SortAlgorithm()
{
int num[] = { 4,8,5,9,6,2,7,3,1 };
vector<int>v;
v.assign(num, num + 9);
//sort(v.begin(), v.end());//sort和stable_sort需要访问随机访问型迭代器，所以只能对vector和deque有用
//对于sort里第三个函数的排序问题可参考此题 https://www.nowcoder.com/pat/6/problem/4041
Print(v);
partial_sort(v.begin(), v.begin() + 5, v.end());//保证前5个元素是已排列的
nth_element(v.begin(), v.begin() + 5, v.end());//保证位置5处左边的都比它小，右边的都比他大。但是vs上是全排列？
Print(v);
}
//合并，交集，差集算法
void MergeAndOther()
{
int num[] = { 1,2,3,4,5,6,7,8 };
int num2[] = { 3,4,5,6,7,8,9,10 };
vector<int>v;
v.assign(num, num + 8);
set<int>s;
for (auto i : num2)
s.insert(i);

vector<int>res;
//将v与s合并到res中,注：要保证v和s是有序的
auto p = merge(v.begin(), v.end(), s.begin(), s.end(), back_inserter(res));
Print(res);

res.clear();
//两个已排序集合的并集
set_union(v.begin(), v.end(), s.begin(), s.end(), back_inserter(res));
Print(res);

res.clear();
//两个已排序集合的交集
set_intersection(v.begin(), v.end(), s.begin(), s.end(), back_inserter(res));
Print(res);

res.clear();
//两个已排序集合的差集，新生元素是含在第一个源区间中的元素
set_difference(v.begin(), v.end(), s.begin(), s.end(), back_inserter(res));
Print(res);
}
//删除算法
void DeleteElement()
{
int num[] = { 1,2,3,3,5,6,7,8 };
vector<int>v;
v.assign(num, num + 8);

//移除重复元素，并返回删除后容器的末尾位置的迭代器,此位置非常重要
auto p = unique(v.begin(), v.end());
v.erase(p, v.end());
Print(v);

//删除区间内为3的元素，返回值同上
auto p2 = remove(v.begin(), v.end(), 3);
v.erase(p2, v.end());//必须要删除掉末尾的几个元素
//for_each(v.begin(), p, [](int t) {cout << t << ","; });
Print(v);

//删除所有大于3的元素
auto p3 = remove_if(v.begin(), v.end(), [](int t) {return t > 3; });
v.erase(p3, v.end());
Print(v);
}