目前会展相关网站的建设情况,上传电影网站源码,免费网站建设链接很长 知呼,生产网线需要什么设备注意事项 #xff1a;
实际使用的时候#xff0c;使用的是algorithm这个头文件#xff0c;不是题目中的 stl_algobase.h
equal函数
如果两个序列在#xff3b;firsLlast#xff09; 区间内相等#xff0c;equal() 返 回 true.如果第二序列的元素比较…注意事项
实际使用的时候使用的是algorithm这个头文件不是题目中的 stl_algobase.h
equal函数
如果两个序列在firsLlast 区间内相等equal() 返 回 true.如果第二序列的元素比较多多出来的元素不予考虑。因此如果我们希望保证两个序列完全相等必须先判断其元素个数是否相同int ia[9] {0,1,2,3,4,5,6,7,8};std::vectorint iv1(ia,ia5);std::vectorint iv2(ia,ia9);if(iv1.size() iv2.size() std::equal(iv1.begin(),iv1.end(),iv2.begin())){}
抑或使用容器所提供的equality操作符例如 vecl vec2.如果第二序列的 元素比第一序列少这个算法内部进行迭代行为时会超越序列的尾端造成不可预测的结果第一版本缺省采用元素型别所提供的equality操作符来进行大小比 较第二版本允许我们指定仿函数pred作为比较依据fill
将 [first/ last) 内的所有元素改填新值. int ia[9] {0,1,2,3,4,5,6,7,8};std::vectorint iv1(ia,ia5);std::vectorint iv2(ia,ia9);std::fill(iv2.begin(),iv2.end(),-1);for (auto elem:iv2) {std::cout elem ;}std::cout \n; fill_n
将[firsllast)内的前n 个元素改填新值返回的迭代器指向被填入的最后一个元素的下一位置。如果n 超越了容器的现有大小会造成什么结果例如我们很容易就可以从源代码知道由于每次迭代进行的是assignment操作是一种覆写(overwrite)操作所以一旦操作区间超越了容器 大小就会造成不可预期的结果。解决办法之一是利用inserter ()产生一个具 有插入(insert)而非覆写(overwrite)能力的迭代器。inserter( ) 可产生一个用来修饰迭代器的配接器(iterator adapter)。用法如下
int main(int argc,char* argv[]) {int ia[9] {0,1,2};std::vectorint iv1(ia,ia3);std::fill(iv1.begin(),iv1.end(),-1);std::fill_n(iv1.begin(),5,7);for (auto elem:iv1) {std::cout elem ;}std::cout \n;
} 但是实际使用的时候 并没有出现问题iter_swap iter_swap( ) 是 “迭代器之valuetype派上用场的一个好例子。是的该函数 必须知道迭代器的veluetype,才能够据此声明一个对象用来暂时存放迭代器所 指对象。为此上述源代码特别设计了一个双层构造第一层调用第二层并多出一个额外的参数value_type(a) 这么一来第二层就有VClIue type可以用了。乍见之下你可能会对这个额外参数在调用端和接受端的型别感到讶异调用端是value_type (a), 接受端却是T*。只要找出value_type ()的定义瞧瞧就一点也不奇怪了
#include iostream
#include algorithm
#include vector
#include random
#include functionaltemplateclass ForwardIt
void selection_sort(ForwardIt begin,ForwardIt end){for (ForwardIt i begin;i!end;i) {std::iter_swap(i,std::min_element(i,end));}
}
int main(int argc,char* argv[]) {std::random_device rd{};std::mt19937 gen(rd());std::uniform_int_distributiondist(-9,9);std::vectorintv{};std::generate_n(std::back_inserter(v),20,std::bind(dist,gen));std::cout Before sort: std::showbase;for (auto e:v) {std::coute ;}selection_sort(v.begin(),v.end());std::cout\nAfter sort:;for (auto e:v) {std::cout e ;}}
lexicographic al_.com pare
以 “字典排列方式”对两个序列firstlAastl)和 first2,last2)itt行比较。比较操作针对两序列中的对应位置上的元素进行并持续直到(1 )某一组对应元素彼此不相等(2 )同时到达last1 和 last2 (当两序列的大小相同)⑶ 到 达 lastl或last2 (当 两 序 列 的 大 小 不 同 )。第一序列以字典排列方式(lexicographically)而言不小于第二序列第二版本允许你指定一个仿函数comp作为比较操作之用取代元素型别所提 供 的 less-than (小 于 )操 作 符 #include iostream
#include algorithm
#include vector
#include randomint main(int argc,char* argv[]) {std::vectorcharv1{a,b,c,d};std::vectorcharv2{a,b,c,d};std::mt19937 g{std::random_device{}()};while (!std::lexicographical_compare(v1.begin(),v1.end(),v2.begin(),v2.end())){for (auto c:v1) std::cout c ;std::cout ;for (auto c:v2) std::cout c ;std::cout \n;std::shuffle(v1.begin(),v1.end(),g);std::shuffle(v2.begin(),v2.end(),g);}for (auto c:v1) std::cout c ;std::cout ;for (auto c:v2) std::cout c ;std::cout \n;
}
mism atch
用来平行比较两个序列指出两者之间的第一个不匹配点。返回一对迭代器分别指向两序列中的不匹配点如下图。如果两序列的所有对应元素都匹配返回的便是两序列各自的last迭代器。缺省情况下是以equality操作符来比较元素 但第二版本允许用户指定比较操作。如果第二序列的元素个数比第一序列多多出来的元素忽略不计。如果第二序列的元素个数比第一序列少会发生未可预期的行为。#include iostream
#include algorithm
#include vector
#include randombool mypredicate(int i,int j){return (ij);
}int main(int argc,char* argv[]) {std::vectorintmy_vector{};for (int i 1; i 6; i) {my_vector.emplace_back(i*10);//10 20 30 40 50 }int myints[] {10,20,80,320,1024};std::pairstd::vectorint::iterator,int*mypair;mypair std::mismatch(my_vector.begin(),my_vector.end(),myints);std::cout First mismatching elements: *mypair.first;std::cout and *mypair.second std::endl;mypair.first;mypair.second;mypair std::mismatch(mypair.first,my_vector.end(),mypair.second, mypredicate);std::cout Second mismatching elements: *mypair.first;std::cout and *mypair.second std::endl;return 0;
}
copy----- 强化效率无所不用其极
不论是对客端程序或对STL内部而言 copy() 都是一个常常被调用的函数。由 于 copy进行的是复制操作而复制操作不外乎运用assignment operator或 copy constructor (copy算法用的是前者)但是某些元素型别拥有的是trivial assignment operator, 因此如果能够使用内存直接复制行为(例如C 标准函数memmove或 memcpy) , 便能够节省大量时间。为此SGI STL的 copy 算法用尽各种办法包括函数重载(function overloading) 、型别特性(type traits)、偏特 化 (partial specialization) 等编程技巧无所不用其极地加强效率。图 6-2表ZK整个copy() 操作的脉络。配合稍后出现的源代码可收一目了然之效。copy算法可将输入区间first, last)内的兀素复制到输出区间result, result(last-first)) 内• 也就是说它会执行赋值操作 *result *first, * (result 1) * ( f irst 1) , … 依 此 类 推 。 返 回 一 个 迭 代 器 result(last-first) copy 对其template参数所要求的条件非常宽松。其输入区间只需由Inputiterators构成即可输出区间只需由Outputiterator构成即可。这意味着你可以使用copy算法将任何容器的任何一段区间的内容复制到任何 容器的任何一段区间上如果输入区间和输出区间完全没有重叠当然毫无问题否则便需特别注意•为什么图6-3第二种情况(可能)会产生错误从稍后即将显示的源代码可知copy 算法是一一进行元素的赋值操作如果输出区间的起点位于输入区间内copy算法便(可能)会在输入区间的(某些)元素尚未被复制之前就覆盖其值导致错误结果.在这里我一再使用“可能”这个字眼是因为如果copy算法根据其所 接收的迭代器的特性决定调用 memmove() 来执行任务就不会造成上述错误因 为 memmove() 会先将整个输人区间的内容复制下来没有被覆盖的危险。int ia[] {0,1,2,3,4,5,6,7,8};//输出区间的终点和输入的区间重叠 没有问题std::copy(ia2,ia7,ia);std::for_each(ia,ia9,displayint());std::cout \n; // 以下输出区间的起点与输入区间重叠可能会有问题int ia[] {0,1,2,3,4,5,6,7,8};std::copy(ia2,ia7,ia4);std::for_each(ia,ia9,displayint());std::cout \n; //0 1 2 3 2 3 4 5 6 int ia[] {0,1,2,3,4,5,6,7,8};//deque 拥有 RandomAcCGSSltGrCltorstd::dequeintid(ia,ia9);std::dequeint::iterator first id.begin();std::dequeint::iterator last id.end();first; //advance(first,2);std::cout *first std::endl; //2----last; //advance(last,-2);std::cout *last std::endl; //7std::dequeint::iterator result std::begin(id);std::cout * result std::endl;// 以下输出区间的终点与输入区间重叠没问题std::copy(first,last,result);//(2 3 4 5 6) 5 6 7 8std::for_each(id.begin(),id.end(),displayint{});std::cout \n;return 0; int ia[] {0,1,2,3,4,5,6,7,8};//deque 拥有 RandomAcCGSSltGrCltorstd::dequeintid(ia,ia9);std::dequeint::iterator first id.begin();std::dequeint::iterator last id.end();first; //advance(first,2);std::cout *first std::endl; //2----last; //advance(last,-2);std::cout *last std::endl; //7std::dequeint::iterator result std::begin(id);std::advance(result,4);std::cout * result std::endl;//以下输出区间的起点与输入区间重叠可能会有问题//本例结果错误因为调用的 copy算法不再使用memmove ()执行实际复制操作std::copy(first,last,result);//0 1 2 3 (2 3 4 5 6std::for_each(id.begin(),id.end(),displayint{});std::cout \n;return 0;
请注意如果你以vector取代上述的deque进行测试复制结果将是正确的因 为 vector迭代器其实是个原生指针(native pointer), 见4.2.3节导致调用的copy算法以memmove ()执行实际复制操作copy更改的是result,result (last-first)) 中的迭代器所指对象而非更改迭代器本身。它会为输出区间内的元素赋予新值而不是产生新的元素。它不能改变输出区间的迭代器个数。换句话说 , copy不能直接用来将元素插入空容器中。例子如下所示如果不给myvector申请空间就会出错只有申请空间之后初始化为0然后执行覆盖原有数值的操作如果你想要将元素插入(而非赋值)序列之内要么明白使用序列容器的insert 成员函数要么使用 copy 算法并搭配 insert_iterator (8.3.1 节 )现在我们来看看 copy算法庞大的实现细节。下面是冰山一角也是唯一的对外接口
int main(int argc,char* argv[]) {int myints[]{10,20,30,40,50,60,70};std::vectorintmyvector(7);std::copy(myints,myints7,myvector.begin());std::cout myvector contains:;for (std::vectorint::iterator it myvector.begin();it ! myvector.end();it) {std::cout *it;}std::cout \n;return 0;
} 下面两个是多载函数针对原生指针(可视为一种特殊的迭代器)const char*和 const wchar_t*, 进行内存直接拷贝操作这里必须兵分两路来探讨。首先_ copy_dispatch ()的完全泛化版根据迭代器种类的不同调用了不同的 一copy() 为的是不同种类的迭代器所使用的循 环条件不同有快慢之别.这 是 __copy_dispatch ()完全泛化版的故事。现在回到前述兵分两路之处 看看它的两个偏特化版本。这两个偏特化版是在“参数为原生指针形式”的前提下希望进一步探测“指针所指之物是否具有trivial assignment operator (平凡 赋值操作符)” • 这一点对效率的影响不小因为这里的复制操作是由assignment 操作符负责如果指针所指对象拥有non-trivial assignment operator,复制操作就 一定得通过它来进行。但如果指针所指对象拥有的是trivial assignment operator, 复制操作可以不通过它直接以最快速的内存对拷方式(memmove ())完成。C语言本身无法让你侦测某个对象的型别是否具有trivial assignment operator,但是SGI STL采用所谓的 type_traits 编程技巧来弥补(见3.7节)。注意通 过 “增 加一层间接性”的手法我们便得以区分两个不同的 copy_t():第三个问题的解答是我们以为vector的迭代器是random access iterator,没想到它事实上是个T* vector迭代器其实是原生指针。这就怪不得copy。 一旦面对vector 迭代器就往T*的方向走去了6.4.4 copy_backw ard
将firstaast)区间内的每一个元素以逆行的方向复制到 以 result-1为起点方向亦为逆行的区间上。换句话说copy_backward算法会 执行赋值操作 * (result-1) * (last-1) , * (result-2 ) * (last-2 ) , 依此类推。返回一个迭代器result- (last-first) □ copy_backward所接受的迭代器必 须 是 Bidirectionallterators, 才 能 够 “倒行逆施”。你可以使用copy_backward算 法将任何容器的任何一段区间的内容复制到任何容器的任何一段区间上°如果输 入区间和输出区间完全没有重叠当然毫无问题否则便需特别注意int ia[] {0,1,2,3,4,5,6,7,8};//输出区间的终点和输入区间重叠 没问题std::copy_backward(ia2,ia7,ia9);std::for_each(ia,ia9,displayint{});//0 1 2 3 2 3 4 5 6std::coutstd::endl;return 0; int ia[] {0,1,2,3,4,5,6,7,8};//输出区间的起点和输入区间重叠 可能会有问题std::copy_backward(ia2,ia7,ia5);std::for_each(ia,ia9,displayint{});//2 3 4 5 6 5 6 7 8//本例结果正确因为调用的copy算法使用memmove ()执行实际复制操作std::coutstd::endl;return 0; templateclass T
struct display{void operator()(const Tx){std::cout x ;}
};
int main(int argc,char* argv[]) {int ia[] {0,1,2,3,4,5,6,7,8};std::dequeintid(ia,ia9);std::dequeint::iterator first id.begin();std::dequeint::iterator last id.end();first; //advance(first,2);std::cout *first std::endl;----last; //advance(last,-2);std::cout *last std::endl;std::dequeint::iterator result id.end();//输出区间的终点和输入区间重叠 没有问题std::copy_backward(first,last,result);std::for_each(id.begin(),id.end(),displayint{});//0 1 2 3 2 3 4 5 6std::coutstd::endl;return 0;
}
int main(int argc,char* argv[]) {int ia[] {0,1,2,3,4,5,6,7,8};std::dequeintid(ia,ia9);std::dequeint::iterator first id.begin();std::dequeint::iterator last id.end();first; //advance(first,2);std::cout *first std::endl;----last; //advance(last,-2);std::cout *last std::endl;std::dequeint::iterator result id.begin();std::advance(result,5);std::cout *result std::endl;//输出区间的起点和输入区间重叠 可能会有问题std::copy_backward(first,last,result);// 本例结果错误因为调用的copy算法不再使用memmove()执行实际复制操作 但是我实际编码结果是正确的std::for_each(id.begin(),id.end(),displayint{});//2 3 4 5 6 5 6 7 8std::coutstd::endl;return 0;
}