STL源码剖析 数值算法 heap算法

算法

  • 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 学生对象数组

题目 代码 package lesson.l10_oop;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/1 9:57* function*/ public class Student {int number;int state;int score;public static final int NUM 20;public static void main(String[] args) { // 对…

STL源码剖析 lower_bound | upper_bound | binary_search

lower_bound 二分查找的一种版本&#xff0c;试图在已经排序的区间内查找元素value&#xff0c;如果区间内存在和value数值相等的元素&#xff0c;便返回一个迭代器&#xff0c;指向其中的第一个元素。如果没有数值相等的元素&#xff0c;会返回假设这个元素存在的前提下应该出…

java 匿名对象

概念 代码 package lesson.l10_oop;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/1 13:39* function 匿名对象*/ public class Anonymous {public static void main(String[] args) { // 用法1new Teacher().say("dq");new Teacher()…

STL源码剖析 第七章 仿函数(函数对象)

函数对象&#xff1a;具有函数性质的对象使得用户像使用函数一样使用它一般函数提供两个版本&#xff0c;第一个版本使用operator < ;第二版本需要用户 指定某种操作第二版本就是设计一个函数&#xff0c;将函数指针作为算法的一个参数&#xff1b;或者将函数操作设计成为一…

开源合同管理系统_「物联网架构」最适合物联网的开源数据库

物联网产生大量的数据&#xff0c;包括流数据、时间序列数据、RFID数据、传感数据等。要有效地管理这些数据&#xff0c;就需要使用数据库。物联网数据的本质需要一种不同类型的数据库。以下是一些数据库&#xff0c;当与物联网一起使用时&#xff0c;会给出非常好的结果。物联…

java 方法重载

概念 代码 package lesson.l10_oop;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/1 14:31* function 方法重载*/ public class Load {public static void main(String[] args) {Load load new Load();load.mOL(4);load.mOL(4, 5);load.mOL("ff&qu…

STL源码剖析 第八章 配接器

设计模式&#xff1a;将一个类的接口转化为另外一个类的接口 配接器的概观和分类 改变仿函数接口 函数配接器 &#xff1b;queue和stack 通过修饰deque函数接口来实现改变容器接口 容器配接器 &#xff1b; insert、reverse、iostream 等iterators他们的接口可以由ite…

python中random库_python标准库之random模块

Python中的random模块用于生成随机数。 下面具体介绍random模块的功能&#xff1a; 1.random.random() #用于生成一个0到1的 随机浮点数&#xff1a;0< n < 1.0 1 import random 2 a random.random() 3 print (a)2.random.uniform(a,b) #用于生成一个指定范围内的随机符…

java 可变个数形参

概念 案例 package lesson.l10_oop;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/1 14:53* function 可变个数形参*/ public class ChangeableFormalParameter {public static void main(String[] args) {ChangeableFormalParameter parameter new Ch…

C++标准库 第七章 STL迭代器

迭代器 能力&#xff1a;行进和存取的能力Input迭代器 一次一个向前读取元素&#xff0c;按此顺序一个一个返回元素例子&#xff1a;从标准输入装置(键盘) 读取数据&#xff0c;同一个数据不会被读取两次&#xff0c;流水一样&#xff0c;指向的是逻辑位置使用前置式递增运算…

nacos集群的ap cp切换_阿里Nacos-配置-多环境

多环境的配置隔离是配置中心最基础的一个功能之一。不同的环境配置的值不一样&#xff0c;比如数据库的信息&#xff0c;业务的配置等。Spring Boot 多环境配置首先我们来回顾下在Spring Boot中用配置文件的方式怎么进行环境的隔离。默认我们都会创建一个application.propertie…

java 值传递机制

说明 案例1 案例2 案例3 案例4 案例5 案例6 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/2 21:24* function 将对象作为参数传递给方法*/ public class Circle {double radius;public double findArea() {return Math.PI * Ma…

密码学专题 非对称加密算法指令概述 RSA

非对称加密算法也称为公开密钥算法&#xff0c;其解决了对称加密算法密钥需要预分配的难题&#xff0c;使得现代密码学的研究和应用取得了重大发展。非对称加密算法的基本特点如下: 加密密钥和解密密钥不相同;密钥对中的一个密钥可以公开(称为公开密钥);根据公开密钥很难推算出…

python元胞自动机模拟交通_结构专栏 | 解析DEFORM软件中的元胞自动机法

点击上方蓝色字体&#xff0c;关注我们导语金属材料的性能取决于内部的微观组织结构&#xff0c;而好的材料性能和价格是产品最大的优势。随着现代物理冶金、热成形技术、热处理技术和计算机技术的兴起与发展&#xff0c;使预测和控制金属材料热加工过程中的组织演变成为可能。…

java 递归

概念 代码 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/2 21:42* function 递归&#xff1a;求n个数的和、乘积*/ public class Recursion {public static void main(String[] args) {Recursion recursion new Recursion();S…

密码学专题 非对称加密算法指令概述 DH算法指令

DH概述 用于密钥交换的公开算法&#xff0c;广泛应用于各种安全协议SSL协议同样支持DH算法DH算法使用之前需要预先共享两个参数&#xff0c;本原元g和模n&#xff0c;这两个参数影响到算法的安全性&#xff0c;因此需要预先生成并检测其安全性生成这些必要参数和管理这些参数的…

java 封装和隐藏 权限修饰符

概念 问题的引入 封装性的体现 权限修饰符 案例 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/3 15:28* function*/ public class Person {private int age;public void setAge(int age) { /* if (age<0||age>…

密码学专题 非对称加密算法指令概述 DSA算法指令

DSA算法和DSA指令概述 DSA算法是美国国家标准的数字签名算法&#xff0c;只具备数字签名的功能不具备密钥交换的功能生成DSA参数然后生成DSA密钥&#xff0c;DSA参数决定了DSA密钥的长度三个指令首先是dsaparam指令&#xff0c;该指令主要用来生成DSA密钥参数&#xff0c;并提…

每天定时打开某个网页_Python科普帖定时通知

0 复习上一关我们学习了selenium&#xff0c;它有可视模式与静默模式这两种浏览器的设置方法&#xff0c;二者各有优势。然后学习了使用.get(URL)获取数据&#xff0c;以及解析与提取数据的方法。在这个过程中&#xff0c;我们操作对象的转换过程&#xff1a;除了上面的方法&am…

java 构造器

概念 案例1 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/3 15:28* function*/ public class Person {private int age;private String name;public Person() {this.age 18;}public Person(int age, String name) {this.age …