算法
- adjacent_find
- count
- count_if
- find
- find_if
- find_end
- for_each
- generate
- generate_n
- includes
- max_element
- merge
- min_element
- partition
- remove
- remove
- remove_copy
- remove_if
- remove_copy_if
- replace
- replace_copy
- replace_if
- replace_copy_if
- reverse
- reverse_copy
- rotate
- rotate_copy
- search
- search_n
- swap_ranges
- transform
- unique
- unique_copy
adjacent_find
- 找出第一组满足条件的相邻元素,版本一是指两个元素相等;版本二允许用户指定一个二元运算,两个操作数分别是相邻的第一元素和第二元素
#include <iostream>
#include <vector>template <class ForwardIterator>
ForwardIterator adjacent_find(ForwardIterator first,ForwardIterator last){if (first != last){ForwardIterator next = first; ++next;while(next != last){if(*first == *next){return first;}++first;++next;}}return last;
}bool myfunction(int i,int j){return (i == j);
}int main(){int myints[] = {5,20,5,30,30,20,10,10,20};std::vector<int>my_vector(myints,myints+8);std::vector<int>::iterator it;//using default comparisonit = std::adjacent_find(my_vector.begin(),my_vector.end());if (it != my_vector.end())std::cout << "The first pair of repeated elements are:" << *it << '\n';//using predicate comparison//it当前指定的位置是30, 自增错过相邻的一堆元素 30it = std::adjacent_find(++it,my_vector.end(), myfunction);if (it != my_vector.end())std::cout << "The first pair of repeated elements are:" << *it << '\n';
}///Users/chy/Desktop/exceptional/cmake-build-debug/exceptional
//The first pair of repeated elements are:30
//The first pair of repeated elements are:10
//
//Process finished with exit code 0
Count
- 运用equality操作符号,将[first,last)内的所有元素和指定的数值value进行比较,并返回和value相等的个数
template <class InputIterator,class T>
typename std::iterator_traits<InputIterator>::difference_type
count(InputIterator first,InputIterator last,const T& value){typename std::iterator_traits<InputIterator>::difference_type ret = 0;while (first!=last){if (*first == value){++ret;}++first;}return ret;
}
// count algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::count
#include <vector> // std::vectorint main () {// counting elements in array:int myints[] = {10,20,30,30,20,10,10,20}; // 8 elementsint mycount = std::count (myints, myints+8, 10);std::cout << "10 appears " << mycount << " times.\n";// counting elements in container:std::vector<int> myvector (myints, myints+8);mycount = std::count (myvector.begin(), myvector.end(), 20);std::cout << "20 appears " << mycount << " times.\n";return 0;
}
count_if
- 使用仿函数pred实施于[first,last) 区间内的每一个元素身上,只要仿函数pred返回为true就进行计数
template <class InputIterator,class UnaryPredicate>
typename std::iterator_traits<InputIterator>::difference_type
count_if(InputIterator first,InputIterator last,UnaryPredicate pred){typename std::iterator_traits<InputIterator>::difference_type ret = 0;while (first!=last){if (pred(*first)){++ret;}++first;}return ret;
}
// count_if example
#include <iostream> // std::cout
#include <algorithm> // std::count_if
#include <vector> // std::vectorbool IsOdd (int i) { return ((i%2)==1); }int main () {std::vector<int> myvector;for (int i=1; i<10; i++) myvector.push_back(i); // myvector: 1 2 3 4 5 6 7 8 9int mycount = count_if (myvector.begin(), myvector.end(), IsOdd);std::cout << "myvector contains " << mycount << " odd values.\n";return 0;
}
find函数
- 循环查找,找到第一个匹配的条件者,返回一个迭代器指向这个元素,否则返回迭代器last
template<class InputIterator, class T>InputIterator find (InputIterator first, InputIterator last, const T& val)
{while (first!=last) {if (*first==val) return first;++first;}return last;
}
// find example
#include <iostream> // std::cout
#include <algorithm> // std::find
#include <vector> // std::vectorint main () {// using std::find with array and pointer:int myints[] = { 10, 20, 30, 40 };int * p;p = std::find (myints, myints+4, 30);if (p != myints+4)std::cout << "Element found in myints: " << *p << '\n';elsestd::cout << "Element not found in myints\n";// using std::find with vector and iterator:std::vector<int> myvector (myints,myints+4);std::vector<int>::iterator it;it = find (myvector.begin(), myvector.end(), 30);if (it != myvector.end())std::cout << "Element found in myvector: " << *it << '\n';elsestd::cout << "Element not found in myvector\n";return 0;
}
find_if
template<class InputIterator, class UnaryPredicate>InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{while (first!=last) {if (pred(*first)) return first;++first;}return last;
}
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vectorbool IsOdd (int i) {return ((i%2)==1);
}int main () {std::vector<int> myvector;myvector.push_back(10);myvector.push_back(25);myvector.push_back(40);myvector.push_back(55);std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);std::cout << "The first odd value is " << *it << '\n';return 0;
}
find_end
- 在序列一[first1,last1)的区间查找序列二[first2,last2)的最后一次出现点,如果序列一不存在完全匹配序列二的子序列就返回迭代器last1
- 如果具备逆向查找的能力,算法的思想就变成了首次出现的地点,逆向查找的关键在于迭代器的双向移动的能力
- 最后需要将逆向迭代器转化为正向迭代器,而不是直接移动逆向迭代器,因为正向迭代器和逆向迭代器之间存在奇妙的实体关系和逻辑关系
template<class ForwardIterator1, class ForwardIterator2>ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2)
{if (first2==last2) return last1; // specified in C++11ForwardIterator1 ret = last1;while (first1!=last1){ForwardIterator1 it1 = first1;ForwardIterator2 it2 = first2;while (*it1==*it2) { // or: while (pred(*it1,*it2)) for version (2)++it1; ++it2;if (it2==last2) { ret=first1; break; }if (it1==last1) return ret;}++first1;}return ret;
}
// find_end example
#include <iostream> // std::cout
#include <algorithm> // std::find_end
#include <vector> // std::vectorbool myfunction (int i, int j) {return (i==j);
}int main () {int myints[] = {1,2,3,4,5,1,2,3,4,5};std::vector<int> haystack (myints,myints+10);int needle1[] = {1,2,3};// using default comparison:std::vector<int>::iterator it;it = std::find_end (haystack.begin(), haystack.end(), needle1, needle1+3);if (it!=haystack.end())std::cout << "needle1 last found at position " << (it-haystack.begin()) << '\n';int needle2[] = {4,5,1};// using predicate comparison:it = std::find_end (haystack.begin(), haystack.end(), needle2, needle2+3, myfunction);if (it!=haystack.end())std::cout << "needle2 last found at position " << (it-haystack.begin()) << '\n';return 0;
}
find_first_of
- 返回第二个序列中元素在第一序列第一次匹配的的地点
- 例子:找出字符串synesthesia中元音字母(第二序列 aeiou),即找出第二序列中任意元素出现于第一序列的地点,此例将返回第一个 e;
- 如果第一序列不包含任何第二序列中的任何元素返回的将是last1
- 算法第一个版本使用元素型别提供的equality操作符号,第二版本使用用户指定的pred二元运算符号
template<class InputIterator,class ForwardIterator>
ForwardIterator find_first_of(InputIterator first1,InputIterator last1,ForwardIterator first2,ForwardIterator last2){while (first1 != last1){for (ForwardIterator it = first2;it!=last2;++it) {if (*it == *first1){return first1;}}++first1;}return last1;
}
bool comp_case_insensitive(char c1,char c2){return (std::tolower(c1)==std::tolower(c2));
}int main(){int mychars[] = {'a','b','c','A','B','C'};std::vector<char>hasstack(mychars,mychars+6);std::vector<char>::iterator it;int needle[] = {'A','B','C'};//using default comparisonit = std::find_first_of(hasstack.begin(),hasstack.end(),needle,needle+3);if (it != hasstack.end()){std::cout << "The first match is: " << *it << '\n';}//using predicate comparisonit = std::find_first_of(hasstack.begin(),hasstack.end(),needle,needle+3, comp_case_insensitive);if (it != hasstack.end()){std::cout << "The first match is: " << *it << '\n';}
}
for_each
- 将仿函数定义于[first,last)区间内的每一个元素的身上
- 但是仿函数f不可以改变元素的内容,因为使用的迭代器的类型都是InputIterators,不保证接受赋值的行为
- 如果需要对元素的数值进行修改,需要使用算法 transform
- 仿函数可以返回一个数值,但是这个数值一般会被忽略
template<class InputIterator, class Function>Function for_each(InputIterator first, InputIterator last, Function fn)
{while (first!=last) {fn (*first);++first;}return fn; // or, since C++11: return move(fn);
}
void myfunction(int i){ //functionstd::cout << i << ' ';
}struct myclass { //function object typevoid operator()(int i){std::cout << i << ' ';}
}myobject;int main(){std::vector<int>myvector;myvector.emplace_back(10);myvector.emplace_back(20);myvector.emplace_back(30);std::cout << "myvector contains: ";std::for_each(myvector.begin(),myvector.end(), myfunction);std::cout << '\n';std::cout << "myvector contains: ";std::for_each(myvector.begin(),myvector.end(), myobject);
}
generate
- 将仿函数gen的运算结果填写在[first ,last)区间内的所有元素身上
- 填写使用的是迭代器所指元素的 assignment 操作符
template <class ForwardIterator, class Generator>void generate ( ForwardIterator first, ForwardIterator last, Generator gen )
{while (first != last) {*first = gen();++first;}
}
//function generator
int RandomNumber(){return (std::rand()%100);
}
//class generator
struct c_unique{int current;c_unique(){current = 0;}int operator()(){return ++current;}
}UniqueNumber;int main(){std::srand(unsigned (std::time(0)));std::vector<int>myvector(8);std::generate(myvector.begin(),myvector.end(),RandomNumber);std::cout << "myvector contains:";for(std::vector<int>::iterator it = myvector.begin();it!=myvector.end();++it){std::cout << *it << ' ';}std::cout << '\n';std::generate(myvector.begin(),myvector.end(),UniqueNumber);std::cout << "myvector contains:";for(std::vector<int>::iterator it = myvector.begin();it!=myvector.end();++it){std::cout << *it << ' ';}std::cout << '\n';
}
generate_n
- 将仿函数gen的运算结果填写在first开始的n个元素上
- 填写使用的是迭代器所指元素的 assignment 操作符
template <class OutputIterator, class Size, class Generator>void generate_n ( OutputIterator first, Size n, Generator gen )
{while (n>0) {*first = gen();++first; --n;}
}
// generate_n example
#include <iostream> // std::cout
#include <algorithm> // std::generate_nint current = 0;
int UniqueNumber () { return ++current; }int main () {int myarray[9] = {0};std::generate_n (myarray, 5, UniqueNumber);std::cout << "myarray contains:";for (int i=0; i<9; ++i)std::cout << ' ' << myarray[i];std::cout << '\n';return 0;
}
includes 应用于有序的区间
- 判断序列二是否涵盖于序列一
- 两个序列都要求有序,其内部元素是可以重复的
- 涵盖的含义是其内的所有元素都被另外一个元素包含。
- 判断元素是否相等,必须使用less 或者 greater
- 默认使用递增排序 即operator < 二者等价 ,less可以省略
std::includes(S1.begin(),S1.end(),S2.begin(),S2.end());std::includes(S1.begin(),S1.end(),S2.begin(),S2.end(),std::less<int>());
- 如果是按照从大到小进行排序,就必须使用仿函数 greater
std::includes(S1.begin(),S1.end(),S2.begin(),S2.end(),std::greater<int>());
- 两个序列的元素都可以重复,S1包含一个S2的子集合,假设某个元素在S2出现n次,在S1出现m次,如果m<n 就会报错
//最新版
template <class InputIterator1,class InputIterator2>
bool includes(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2){while (first2 != last2){if (first1 == last1 || (*first2 < *first1)){return false;}if (!(*first1 < *first2)){++first2;}++first1;}return true;
}//旧版
//判断区间二 中的每个元素 数值是否都存在于区间一
//区间一和区间二都是sorted ranges
template <class InputIterator1,class InputIterator2>
bool includes(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2){while(first1!=last1 && first2!=last2){if (*first2 < *first1){return false;} else if(*first2 > *first1){++first1;} else{++first1;++first2;}}return first2 == last2;
}//二元运算 comp
//前提是序列一和序列二都是 sorted ranges
template <class InputIterator1,class InputIterator2,class Compare>
bool includes(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,Compare comp){while(first1!=last1 && first2!=last2){if (comp(*first2,*first1)){return false;} else if(comp(*first1,*first2)){++first1;} else{++first1;++first2;}}return first2 == last2;
}
- 版本二 如果你传入了一个二元运算符comp,却不能使以下的case3代表两个元素相等
- 这个comp会导致整个includes算法语义错误。但是comp的型别是Compare既不是BinaryPredicate 也不是BinaryOperation,所以并非随便一个二元运算符号都可以用于作为comp的参数
// includes algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::includes, std::sortbool myfunction (int i, int j) { return i<j; }int main () {int container[] = {5,10,15,20,25,30,35,40,45,50};int continent[] = {40,30,20,10};std::sort (container,container+10);std::sort (continent,continent+4);// using default comparison:if ( std::includes(container,container+10,continent,continent+4) )std::cout << "container includes continent!\n";// using myfunction as comp:if ( std::includes(container,container+10,continent,continent+4, myfunction) )std::cout << "container includes continent!\n";return 0;
}
max_element
- 返回最大的元素
template <class ForwardIterator>
ForwardIterator max_element(ForwardIterator first,ForwardIterator last){if (first==last){return last;}ForwardIterator largest = first;while(++first!=last){if(*largest < *first){largest = first;}}return largest;
}
Merge 应用于有序区间
- 将两个排序的集合S1和S2,合并起来置于另外一段空间,得到一个有序的序列
- 返回一个迭代器指向最后的结果序列的最后一个元素的位置
template <class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator merge(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result){while(first1 != last1 && first2 != last2){ //两个都尚未走完if (*first2 < *first1){*result = *first2;++first2;} else{*result = *first1;++first1;}++result;}return std::copy(first2,last2,std::copy(first1,last2,result));
}
template <class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator merge(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result){while (true){if (first1 == last1){std::copy(first2,last2,result);}if (first2 == last2){std::copy(first1,last1,result);}*result++ = (*first1 < *first2) ? *first1++ : *first2++;}
}
// includes algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::includes, std::sortbool myfunction (int i, int j) { return i<j; }int main () {int container[] = {5,10,15,20,25,30,35,40,45,50};int continent[] = {40,30,20,10};std::sort (container,container+10);std::sort (continent,continent+4);std::vector<int>v(14,0);std::merge(container,container+10,continent,continent+4,v.begin());for(auto x : v){std::cout << x << ' ';}//5 10 10 15 20 20 25 30 30 35 40 40 45 50 return 0;
}
min_element
template <class ForwardIterator>ForwardIterator min_element ( ForwardIterator first, ForwardIterator last )
{if (first==last) return last;ForwardIterator smallest = first;while (++first!=last)if (*first<*smallest) // or: if (comp(*first,*smallest)) for version (2)smallest=first;return smallest;
}
// min_element/max_element example
#include <iostream> // std::cout
#include <algorithm> // std::min_element, std::max_elementbool myfn(int i, int j) { return i<j; }struct myclass {bool operator() (int i,int j) { return i<j; }
} myobj;int main () {int myints[] = {3,7,2,5,6,4,9};// using default comparison:std::cout << "The smallest element is " << *std::min_element(myints,myints+7) << '\n';std::cout << "The largest element is " << *std::max_element(myints,myints+7) << '\n';// using function myfn as comp:std::cout << "The smallest element is " << *std::min_element(myints,myints+7,myfn) << '\n';std::cout << "The largest element is " << *std::max_element(myints,myints+7,myfn) << '\n';// using object myobj as comp:std::cout << "The smallest element is " << *std::min_element(myints,myints+7,myobj) << '\n';std::cout << "The largest element is " << *std::max_element(myints,myints+7,myobj) << '\n';return 0;
}
partition
- partition会重新排列区间内的元素,将所有被一元条件pred判定为true的元素排列在区间的前段,判定为false的元素排列在后端
- 不稳定算法 不保持相对次序不变
- 如果想保证相对次序不变 使用 stable_partition
template <class BidirectionalIterator,class UnaryPredicate>
BidirectionalIterator partition(BidirectionalIterator first,BidirectionalIterator last, UnaryPredicate pred){while(first != last){while(pred(*first)){++first;if (first == last){return first;}}do{--last;if (first == last){return first;}} while (!pred(*last));std::swap(*first,*last);++first;}
}
remove 移除但是不删除
- 将每一个不与value相等的元素轮番赋值给first之后的空间
- 返回的ForwardIterator标示出重新整理后的最后元素的下一个位置
- 例子:序列{0,1,0,2,0,3,0,4} 移除0元素之后变成 {1,2,3,4,0,3,0,4}每一个与0不相等的元素被拷贝到一、二、三、四个位置,即第四个位置之后是这个算法的残余数据
- array不适用于remove 和 remove_if,因为array无法缩小尺寸,导致残余的数据一直存在
- 对于array,比较适用的算法是remove_copy()和remove_copy_if
template <class ForwardIterator,class T>
ForwardIterator remove(ForwardIterator first,ForwardIterator last,const T& value){ForwardIterator result = first;while(first!=last){if (!(*first==value)){if(!(first==result)){*result = *first;}++result;}++first;}return result;
}
int main () {int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20//bounds of rangeint* begin = myints;int* end = myints + (sizeof (myints)/sizeof (int));end = std::remove(begin,end,20);std::cout << "range contains:";for(int* ptr = begin;ptr!=end;++ptr){std::cout << *ptr << ' ';}std::cout << '\n';
}
remove_copy
- 将每一个不与value相等的元素轮番赋值给result开始的起始容器
- 新的容器可以和先前的容器重叠,但是对于新的容器赋值超越了旧的容器的大小会产生无法预期的后果
- 返回值OutputIterator会指向被复制的最后元素的下一个位置
template <class ForwardIterator,class OutputIterator,class T>
ForwardIterator remove(ForwardIterator first,ForwardIterator last,OutputIterator result,const T& value){while(first!=last){if (!(*first==value)){*result = *first;++result;}++first;}return result;
}
int main () {int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20//bounds of rangeint* begin = myints;int* end = myints + (sizeof (myints)/sizeof (int));std::vector<int>myvector(5);std::remove_copy(begin,end,myvector.begin(),20);std::cout << "range contains:";for(auto ptr = myvector.begin();ptr!=myvector.end();++ptr){std::cout << *ptr << ' ';}std::cout << '\n';
}
remove_if
- 将每一个被pred核定为true的元素轮番赋值给first之后的空间,并不会真的删除元素
- 返回的ForwardIterator标示出重新整理后的最后元素的下一个位置
- 可以通过将迭代器交给所在容器的erase member function
- array不适用于remove 和 remove_if,因为array无法缩小尺寸,导致残余的数据一直存在
- 对于array,比较适用的算法是remove_copy()和remove_copy_if
template <class ForwardIterator,class UnaryPredicate>
ForwardIterator remove_if(ForwardIterator first,ForwardIterator last,UnaryPredicate pred){ForwardIterator result = first;while(first!=last){if (!pred(*first)){if (result != first){*result = *first;}++result;}++first;}return result;
}
// remove_if example
#include <iostream> // std::cout
#include <algorithm> // std::remove_ifbool myfunction (int i, int j) { return i<j; }int main () {int myints[] = {1,2,3,4,5,6,7,8,9}; // 1 2 3 4 5 6 7 8 9// bounds of range:int* pbegin = myints; // ^int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^pend = std::remove_if (pbegin, pend, IsOdd); // 2 4 6 8 ? ? ? ? ?// ^ ^std::cout << "the range contains:";for (int* p=pbegin; p!=pend; ++p)std::cout << ' ' << *p;std::cout << '\n';return 0;
}
remove_copy_if
- 将每一个被pred核定为true的元素赋值给result开始的空间,并不会真的删除元素
- 可以通过将迭代器交给所在容器的erase member function
- array不适用于remove 和 remove_if,因为array无法缩小尺寸,导致残余的数据一直存在
- 对于array,比较适用的算法是remove_copy()和remove_copy_if
template <class InputIterator, class OutputIterator, class UnaryPredicate>OutputIterator remove_copy_if (InputIterator first, InputIterator last,OutputIterator result, UnaryPredicate pred)
{while (first!=last) {if (!pred(*first)) {*result = *first;++result;}++first;}return result;
}
// remove_copy_if example
#include <iostream> // std::cout
#include <algorithm> // std::remove_copy_if
#include <vector> // std::vectorbool IsOdd (int i) { return ((i%2)==1); }int main () {int myints[] = {1,2,3,4,5,6,7,8,9};std::vector<int> myvector (9);std::remove_copy_if (myints,myints+9,myvector.begin(),IsOdd);std::cout << "myvector contains:";for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
replace
- 将指定区间内的所有旧的元素使用新的数值进行替换
template <class ForwardIterator, class T>void replace (ForwardIterator first, ForwardIterator last,const T& old_value, const T& new_value)
{while (first!=last) {if (*first == old_value) *first=new_value;++first;}
}
// replace algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::replace
#include <vector> // std::vectorint main () {int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };std::vector<int> myvector (myints, myints+8); // 10 20 30 30 20 10 10 20std::replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99std::cout << "myvector contains:";for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
replace_copy
- 将新的序列复制到result指定的容器
- 返回的OutputIterator指向被复制的最后一个元素的下一个位置
- 并不会改变先前的序列
template < class ForwardIterator, class UnaryPredicate, class T >void replace_if (ForwardIterator first, ForwardIterator last,UnaryPredicate pred, const T& new_value)
{while (first!=last) {if (pred(*first)) *first=new_value;++first;}
}
// replace_if example
#include <iostream> // std::cout
#include <algorithm> // std::replace_if
#include <vector> // std::vectorbool IsOdd (int i) { return ((i%2)==1); }int main () {std::vector<int> myvector;// set some values:for (int i=1; i<10; i++) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9std::replace_if (myvector.begin(), myvector.end(), IsOdd, 0); // 0 2 0 4 0 6 0 8 0std::cout << "myvector contains:";for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
replace_if
- 将pred判定为true的元素使用新值进行替换
template < class ForwardIterator, class UnaryPredicate, class T >void replace_if (ForwardIterator first, ForwardIterator last,UnaryPredicate pred, const T& new_value)
{while (first!=last) {if (pred(*first)) *first=new_value;++first;}
}
// replace_if example
#include <iostream> // std::cout
#include <algorithm> // std::replace_if
#include <vector> // std::vectorbool IsOdd (int i) { return ((i%2)==1); }int main () {std::vector<int> myvector;// set some values:for (int i=1; i<10; i++) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9std::replace_if (myvector.begin(), myvector.end(), IsOdd, 0); // 0 2 0 4 0 6 0 8 0std::cout << "myvector contains:";for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
replace_copy_if
- 其行为类似replace_if()
- 新的序列会被复制到result指定的区间内
- 返回的OutputIterator指向被复制的最后一个元素的下一个位置
- 并不会改变先前的序列
template <class InputIterator, class OutputIterator, class UnaryPredicate, class T>OutputIterator replace_copy_if (InputIterator first, InputIterator last,OutputIterator result, UnaryPredicate pred,const T& new_value)
{while (first!=last) {*result = (pred(*first))? new_value: *first;++first; ++result;}return result;
}
// replace_copy_if example
#include <iostream> // std::cout
#include <algorithm> // std::replace_copy_if
#include <vector> // std::vectorbool IsOdd (int i) { return ((i%2)==1); }int main () {std::vector<int> foo,bar;// set some values:for (int i=1; i<10; i++) foo.push_back(i); // 1 2 3 4 5 6 7 8 9bar.resize(foo.size()); // allocate spacestd::replace_copy_if (foo.begin(), foo.end(), bar.begin(), IsOdd, 0);// 0 2 0 4 0 6 0 8 0std::cout << "bar contains:";for (std::vector<int>::iterator it=bar.begin(); it!=bar.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
reverse
- 将序列中的元素在原有的容器中颠倒重排
- 根据迭代器的类型 (双向迭代器或者随机迭代器)进行偏特化设计
template <class BidirectionalIterator>void reverse (BidirectionalIterator first, BidirectionalIterator last)
{while ((first!=last)&&(first!=--last)) {std::iter_swap (first,last);++first;}
}
// reverse algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::reverse
#include <vector> // std::vectorint main () {std::vector<int> myvector;// set some values:for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9std::reverse(myvector.begin(),myvector.end()); // 9 8 7 6 5 4 3 2 1// print out content:std::cout << "myvector contains:";for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
reverse_copy_if
- 行为类似reverse
- 新的序列会被复制到result指定的区间内
- 返回的OutputIterator指向被复制的最后一个元素的下一个位置
- 并不会改变先前的序列
template <class BidirectionalIterator, class OutputIterator>OutputIterator reverse_copy (BidirectionalIterator first,BidirectionalIterator last, OutputIterator result)
{while (first!=last) {--last;*result = *last;++result;}return result;
}
// reverse_copy example
#include <iostream> // std::cout
#include <algorithm> // std::reverse_copy
#include <vector> // std::vectorint main () {int myints[] ={1,2,3,4,5,6,7,8,9};std::vector<int> myvector;myvector.resize(9); // allocate spacestd::reverse_copy (myints, myints+9, myvector.begin());// print out content:std::cout << "myvector contains:";for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
rotate
- 将[first,middle)和[middle,last)内的元素互换
- middle指向的元素会成为容器的第一个元素
- 其功能类似swap_ranges,但是swap_ranges只能交换两个长度相同的区间
- rotate可以交换两个长度不同的区间
template <class ForwardIterator>void rotate (ForwardIterator first, ForwardIterator middle,ForwardIterator last)
{ForwardIterator next = middle;while (first!=next){swap (*first++,*next++);if (next==last) next=middle;else if (first==middle) middle=next;}
}
- 先交换元素的数值,再进行迭代器的递增
int main () {int myints[] = {1,2,3,4,5,6,7,8,9}; // 1 2 3 4 5 6 7 8 9std::vector<int>myvector(myints,myints+9);std::rotate(myvector.begin(),myvector.begin()+3,myvector.end());std::cout << "the range contains:";for (auto temp : myvector)std::cout << ' ' << temp;std::cout << '\n'; //the range contains: 4 5 6 7 8 9 1 2 3return 0;
}
rote_copy
- 类似于rote 将产生的新的序列置于result所指出的容器中
- 返回的OutputIterator指向被复制的最后一个元素的下一个位置
- 并不会改变先前的序列
- 操作过程:将后端复制到新的容器的开端,再将前段内容复制到新的容器
template <class ForwardIterator,class OutputIterator>
OutputIterator rotate_copy(ForwardIterator first,ForwardIterator middle,ForwardIterator last,OutputIterator result){result = std::copy(middle,last,result);return std::copy(first,middle,result);
}
int main () {int myints[] = {1,2,3,4,5,6,7,8,9}; // 1 2 3 4 5 6 7 8 9std::vector<int>myvector(myints,myints+9);std::vector<int>my_tmp(9,0);std::rotate_copy(myvector.begin(),myvector.begin()+3,myvector.end(),my_tmp.begin());std::cout << "the range contains:";for (auto temp : my_tmp)std::cout << ' ' << temp;std::cout << '\n'; //the range contains: 4 5 6 7 8 9 1 2 3
// myvector the range contains: 1 2 3 4 5 6 7 8 9return 0;
}
Search
- 在序列一种查找序列二中首次出现的点
- 如果不存在完全匹配的子序列,返回序列一的last
template <class ForwardIterator1,class ForwardIterator2>
ForwardIterator1 search(ForwardIterator1 first1,ForwardIterator1 last1,ForwardIterator2 first2,ForwardIterator2 last2){if(first2 == last2) return first1;while(first1 != last1){ForwardIterator1 it1 = first1;ForwardIterator2 it2 = first2;while (*it1 == *it2){++it1;++it2;if (*it2==last2)return first1;if (*it1==last1)return last1;}++first1;}return last1;
}
// search algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::search
#include <vector> // std::vectorbool mypredicate (int i, int j) {return (i==j);
}int main () {std::vector<int> haystack;// set some values: haystack: 10 20 30 40 50 60 70 80 90for (int i=1; i<10; i++) haystack.push_back(i*10);// using default comparison:int needle1[] = {40,50,60,70};std::vector<int>::iterator it;it = std::search (haystack.begin(), haystack.end(), needle1, needle1+4);if (it!=haystack.end())std::cout << "needle1 found at position " << (it-haystack.begin()) << '\n';elsestd::cout << "needle1 not found\n";// using predicate comparison:int needle2[] = {20,30,50};it = std::search (haystack.begin(), haystack.end(), needle2, needle2+3, mypredicate);if (it!=haystack.end())std::cout << "needle2 found at position " << (it-haystack.begin()) << '\n';elsestd::cout << "needle2 not found\n";return 0;
}
search_n
- 查找连续几个符合条件的元素组成的子序列,返回一个迭代器指向该子序列起始的地方,找不到返回迭代器last
- 版本一使用 equality 版本二使用 用户指定的某个二元函数,使用仿函数实现
- 例子:面对序列 {10,8,8,4,5,2,3,4}查找连续两个8形成的子序列起点
- iter1 = search_n (iv.begin(),iv.end(),2,8);
- 例子:面对序列 {10,8,8,4,5,2,3,4}查找连续三个小于8的子序列起点
- iter1 = search_n (iv.begin(),iv.end(),3,8,std::less<int>());
template <class ForwardIterator,class Size,class T>
ForwardIterator search_n(ForwardIterator first,ForwardIterator last,Size count,const T& val){ForwardIterator it,limit;Size i;limit = first;std::advance(limit,std::distance(first,last)-count);while(first!=limit){it = first;i = 0;while(*it == val){++it;if (++i == count){return first;}}++first;}return last;
}
// search_n example
#include <iostream> // std::cout
#include <algorithm> // std::search_n
#include <vector> // std::vectorbool mypredicate (int i, int j) {return (i==j);
}int main () {int myints[]={10,20,30,30,20,10,10,20};std::vector<int> myvector (myints,myints+8);std::vector<int>::iterator it;// using default comparison:it = std::search_n (myvector.begin(), myvector.end(), 2, 30);if (it!=myvector.end())std::cout << "two 30s found at position " << (it-myvector.begin()) << '\n';elsestd::cout << "match not found\n";// using predicate comparison:it = std::search_n (myvector.begin(), myvector.end(), 2, 10, mypredicate);if (it!=myvector.end())std::cout << "two 10s found at position " << int(it-myvector.begin()) << '\n';elsestd::cout << "match not found\n";return 0;
}
swap_ranges
- 将[first1 ,last1) 区间内的元素和从[first2 开始个数相同的元素互相交换
- 两个区间不限定是否从属于同一个区间 ,可以相同 可以不同
- 如果第二个序列的长度小于第一个序列的长度,或者两个序列在同一个序列中出现重叠,执行结果是不可预期的
- 此算法返回一个迭代器 指向第二序列中最后一个被交换元素的下一个位置
template <class ForwardIterator1,class ForwardIterator2>
ForwardIterator2 swap_ranges(ForwardIterator1 first1,ForwardIterator1 last1,ForwardIterator2 first2){while(first1 != last1){std::swap(*first1,*first2);++first1;++first2;}return first2;
}
// swap_ranges example
#include <iostream> // std::cout
#include <algorithm> // std::swap_ranges
#include <vector> // std::vectorint main () {std::vector<int> foo (5,10); // foo: 10 10 10 10 10std::vector<int> bar (5,33); // bar: 33 33 33 33 33std::swap_ranges(foo.begin()+1, foo.end()-1, bar.begin());// print out results of swap:std::cout << "foo contains:";for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';std::cout << "bar contains:";for (std::vector<int>::iterator it=bar.begin(); it!=bar.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
transform
- 第一版本使用仿函数op作用于区间中每一个元素的身上,产生一个新的序列
- 第二版本使用仿函数binary_op作用于一双元素的身上,第一个元素来自[first,last1),第二个元素来自从first2开始的序列,如果第二序列元素少,会出错
- 两个版本的transform都会把结果放进迭代器result所标示的容器中
- result可以指向源端容器,造成数据的覆盖
- 返回迭代器指向的是结果序列的最后元素的下一个位置
template <class InputIterator, class OutputIterator, class UnaryOperator>OutputIterator transform (InputIterator first1, InputIterator last1,OutputIterator result, UnaryOperator op)
{while (first1 != last1) {*result = op(*first1); // or: *result=binary_op(*first1,*first2++);++result; ++first1;}return result;
}
// transform algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::transform
#include <vector> // std::vector
#include <functional> // std::plusint op_increase (int i) { return ++i; }int main () {std::vector<int> foo;std::vector<int> bar;// set some values:for (int i=1; i<6; i++)foo.push_back (i*10); // foo: 10 20 30 40 50bar.resize(foo.size()); // allocate spacestd::transform (foo.begin(), foo.end(), bar.begin(), op_increase);// bar: 11 21 31 41 51// std::plus adds together its two arguments:std::transform (foo.begin(), foo.end(), bar.begin(), foo.begin(), std::plus<int>());// foo: 21 41 61 81 101std::cout << "foo contains:";for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
unique
- 移除相邻重复的元素
- 移除所有重复的元素需要实现排序
- 返回的迭代器指向新的区间的尾端,新区间内容不重复
- 算法是稳定的,其所有保留下来的元素,其原始相对次序不改变
template <class ForwardIterator>ForwardIterator unique (ForwardIterator first, ForwardIterator last)
{if (first==last) return last;ForwardIterator result = first;while (++first != last){if (!(*result == *first)) // or: if (!pred(*result,*first)) for version (2)*(++result)=*first;}return ++result;
}
// unique algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::unique, std::distance
#include <vector> // std::vectorbool myfunction (int i, int j) {return (i==j);
}int main () {int myints[] = {10,20,20,20,30,30,20,20,10}; // 10 20 20 20 30 30 20 20 10std::vector<int> myvector (myints,myints+9);// using default comparison:std::vector<int>::iterator it;it = std::unique (myvector.begin(), myvector.end()); // 10 20 30 20 10 ? ? ? ?// ^myvector.resize( std::distance(myvector.begin(),it) ); // 10 20 30 20 10// using predicate comparison:std::unique (myvector.begin(), myvector.end(), myfunction); // (no changes)// print out content:std::cout << "myvector contains:";for (it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
unique_copy
template <class InputIterator, class OutputIterator>OutputIterator unique_copy (InputIterator first, InputIterator last,OutputIterator result)
{if (first==last) return result;*result = *first;while (++first != last) {typename iterator_traits<InputIterator>::value_type val = *first;if (!(*result == val)) // or: if (!pred(*result,val)) for version (2)*(++result)=val;}return ++result;
}
// unique_copy example
#include <iostream> // std::cout
#include <algorithm> // std::unique_copy, std::sort, std::distance
#include <vector> // std::vectorbool myfunction (int i, int j) {return (i==j);
}int main () {int myints[] = {10,20,20,20,30,30,20,20,10};std::vector<int> myvector (9); // 0 0 0 0 0 0 0 0 0// using default comparison:std::vector<int>::iterator it;it=std::unique_copy (myints,myints+9,myvector.begin()); // 10 20 30 20 10 0 0 0 0// ^std::sort (myvector.begin(),it); // 10 10 20 20 30 0 0 0 0// ^// using predicate comparison:it=std::unique_copy (myvector.begin(), it, myvector.begin(), myfunction);// 10 20 30 20 30 0 0 0 0// ^myvector.resize( std::distance(myvector.begin(),it) ); // 10 20 30// print out content:std::cout << "myvector contains:";for (it=myvector.begin(); it!=myvector.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}