以下常用算法,来自经典书籍<<STL源码解析>>。
一、数值算法,标准库的仿函数一般用在此处。
accumutate()累加、 inner_product()内积、 partial_sum()相加、 adjacent_difference()相差 ,这些算法只能用在数值上,所以头文件是<numeric>.
另外还有mismatch().
int main()
{
//accumulate() inner_product() partial_sum() adjacent_difference()
int ia[5] = { 1,2,3,4,5 };
vector<int> iv(ia, ia+5);
//数值算法 <numeric>
//仿函数 <functional>
//累加(默认仿函数plus) 支持可调用对象(仿函数:plus minus multiplies divides modulus negate)
cout<< accumulate(iv.begin(), iv.end(), 10) << endl; //10+1+2+3+4+5
cout << accumulate(iv.begin(), iv.end(), 10, minus<int>()); //10-1-2-3-4-5
//两个序列相乘的和(默认参数)
cout << inner_product(iv.begin(), iv.end(), iv.begin(), 10) << endl; //10+1*1+2*2+3*3+4*4+5*5
cout << inner_product(iv.begin(), iv.end(), iv.begin(), 10, minus<int>(), plus<int>()) << endl; //10-1+1-2+2-3+3-4+4-5+5
ostream_iterator<int> oiter(cout, " "); //任意输入到此迭代器的都将输出到屏幕
//等于前面数值相加
//partial_sum(iv.begin(), iv.end(),iv.begin()); //1 3 6 10 15
partial_sum(iv.begin(), iv.end(), oiter); //直接输出到屏幕
partial_sum(iv.begin(), iv.end(), oiter,minus<int>()); //1 -1 -4 -8 -13
cout << endl;
//adjacent_difference() 与partial_sum() 互为逆运算
//相邻元素的差 默认minus<>
adjacent_difference(iv.begin(), iv.end(), oiter); //1 1 1 1 1
adjacent_difference(iv.begin(), iv.end(), oiter, plus<int>()); //1 2 3 7 9 相邻元素的和
cout << endl;
//mismatch equal
int ia1[9] = { 1,2,3,4,5,6,7,8,9 };
vector<int> iv1(ia1, ia1 + 5);
vector<int> iv2(ia1, ia1 + 9);
//比较两个序列第一个不匹配的点,返回pair
auto p_pair = mismatch(iv1.begin(), iv1.end(), iv2.begin(), iv2.end());
if (p_pair.first == iv1.end())
cout << "iv2包含iv1" << endl;
else
cout<<"iv1跟iv2 的第一个不同点在:"<< *(p_pair.first)<<endl;
if (p_pair.second == iv2.end())
cout << "iv1包含iv2" << endl;
else
cout << "iv2跟iv1 的第一个不同点在iv2的元素:" << *(p_pair.second) << endl;
}
二、fill、equal、advance、swap、lexicographical_compare、copy
int main()
{
//equal返回bool 在[first,last)区间相等
cout << equal(iv1.begin(), iv1.end(), iv2.begin()) << endl; //1 iv2超长的部分不考虑,
//第二个序列一定不能比第一个短,否则是未定义行为
//所以要判断完全相等需要先判断队列长度
cout << equal(iv1.begin(), iv1.end(), &ia1[3]) << endl; //0
cout << equal(iv1.begin(), iv1.end(), &ia1[3], less<int>()) << endl;//1 {1,2,3,4,5} 小于{3,4,5,6,7}
//fill
fill(iv1.begin(), iv1.end(), 9);
fill_n(iv1.begin(), 3, 8); //返回迭代器指向插入的下一个位置; 想想如果n超越了先有容器的大小会怎样
fill_n(inserter(iv1,iv1.begin()), 8, 7);//是在头部插入8个7 ,这样就会自动扩容
//for_each
for_each(iv1.begin(), iv1.end(), [](int i) {cout << i << " "; });
cout << endl;
//advance
vector<int>::iterator it1 = iv1.begin();
vector<int>::iterator it2 = it1;
advance(it2, 3);
cout << *it2 << endl;
//只对调元素 且只能通过迭代器 8 8 8 9 9 ->9 8 8 8 9
vector<int>::iterator it22 = iv2.begin();
iter_swap(it1, it22);
for_each(iv1.begin(), iv1.end(), [](int i) {cout << i << " "; }); //8 8 8 9 9 ->1 8 8 9 9
cout << endl;
for_each(iv2.begin(), iv2.end(), [](int i) {cout << i << " "; }); //1 2 3 4 5 6 7 8 9->9 2 3 4 5 6 7 8 9
cout << endl;
//值对调
swap(*iv1.begin(), *iv2.begin());
//对调序列 iv1 iv2对调,对调后原来的迭代器并不失效
swap(iv1, iv2);
for_each(iv1.begin(), iv1.end(), [](int i) {cout << i << " "; }); //1 8 8 9 9 -> 9 2 3 4 5 6 7 8 9
cout << endl;
for_each(iv2.begin(), iv2.end(), [](int i) {cout << i << " "; }); //9 2 3 4 5 6 7 8 9-> 1 8 8 9 9
cout << endl;
//字符串序列比较
vector<string> start1{ "Jamie","JJHou","Jason" };
vector<string> start2{ "Jamie","JJHou","Jeson" };
cout << lexicographical_compare(start1.begin(), start1.end(), start2.begin(), start2.end()) << endl; //1 start1<start2
cout << lexicographical_compare(start1.begin(), start1.end(), start2.begin(), start2.end(), greater<string>()) << endl; //0 start1 不大于 start2
//只是获取两个数的最大\最小,而且只能作用于数值类型 ,用途不大;获取序列的最大、最小用途更广
cout << max(*iv1.begin(), *iv2.begin()) << endl;
cout << min(*iv1.begin(), *iv2.begin()) << endl;
cout << "============================" << endl;
//copy 为了效率 copy的实现相当复杂
int ca[8] = { 0,1,2,3,4,5,6,7 };
//注意这是目标起始位置,在输入数据中间,这种情况很可能会出问题,要慎用
//这里之所以没出问题 (vector起始也不出问题),是因为copy内部的特殊处理,用memmove直接复制了输入的内存,
//进行拷贝的,而如果用list 、deque等是一个元素一个元素的拷贝,就会出问题
auto it =copy(ca + 2, ca + 6, ca + 3); //0,1,2,2,3,4,5,7
//这里换成deque就不是我们预期的结果
//deque<int> de{ 0,1,2,3,4,5,6,7 };
//auto it = copy(de.begin() + 2, de.begin() + 6, de.begin() + 3); //0 1 2 2 2 2 2 7
//所以copy()目标位置的开通不能在输入区间,但结尾可以在输入区间,copy_backward相反
char cha[] = { 'a','b','c','d','e','f','g' };
char cha2[8] = { 0 };
copy_backward(cha, cha + 7, cha2+7); //a b c d e f g
for (auto i : cha2)
printf("%c ", i);
return 0;
}
三、set中用到的并、交、差
set的运算和我们正常理解是一样的,multiset的运算稍微有点差异。
int ar1[] = { 1,3,5,7,9,11 };
int ar2[] = { 1,1,2,3,5,8,13 };
multiset<int> s1(ar1, ar1 + 6);
multiset<int> s2(ar2, ar2 + 7);
multiset<int>::iterator first1 = s1.begin();
multiset<int>::iterator last1 = s1.end();
multiset<int>::iterator first2 = s2.begin();
multiset<int>::iterator last2 = s2.end();
//并集
cout << "Union of s1 and s2: ";
set_union(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); //并集 出现在s1和s2 则以s1为准,
cout << endl; 因为元素不唯一,s1中出现n次,s2中出现m次,并后为max(n,m)
//交集
cout << "difference of s1 and s2: ";
set_intersection(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
cout << endl;
//差集
cout << "difference of s1 and s2: ";
set_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));//差集不唯一的元素 min(n,m)
cout << endl;
//对称差集
cout << "symmetric_difference of s1 and s2: "; //对称差集,在s1中不在s2中,及在s2中不在s1中
set_symmetric_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); //abs(n-m)
cout << endl;