算法附录.docx
- 文档编号:26994928
- 上传时间:2023-06-24
- 格式:DOCX
- 页数:114
- 大小:49.46KB
算法附录.docx
《算法附录.docx》由会员分享,可在线阅读,更多相关《算法附录.docx(114页珍藏版)》请在冰豆网上搜索。
算法附录
泛型算法按字母排序
在本附录中我们将依次介绍每个单独的算法我们选择以字母顺序给出这些算法
除了少数例外以便可以很容易地查阅它们本附录给出这些算法的一般形式
是列出函数原型提供一两段说明性的文字指出某些不直观的行为或可能
性以及最重要的提供一个程序例子来说明怎样使用该算法
所有泛型算法的前两个实参都是一对iterator迭代器通常称为first和last标记出
内置数组或容器中要操作的元素的范围元素范围的表示法有时也被称为左包含区间通
常被写作
//被读作:
包括第一个以及它后面的每一个元素,但是不包括
//最后一个.
[first,last)
表示该范围从first开始直到last结束但是不包括last当表示为以下形式时
first==last
该范围被称为是空的
对于iterator对的要求是它必须能够从first开始通过反复应用递增操作符可以到达
last但是编译器自己不能保证这一点不能满足这个要求将导致未定义的运行时刻行为
——通常是程序的核心转储
每个算法的声明都指出了其iterator必须支持的最小分类关于五个iterator分类的简要
讨论见12.4节例如find()实现了对一个容器的单遍只读遍历它至少需要一个
InputIterator它也可以被传递一个ForwardIteratorBidirectionalIterator或
RamdomAccessIterator然而如果向它传递一个OutputIterator就会引起错误给一个算法
传递一个无效的iterator类别这样的错误并不一定会在编译时刻被检查出来因为iterator类
别不是实际的类型而是被传递给函数模板的类型参数
有些算法支持多个版本一个版本利用内置操作符而另一个版本接受一个函数对象或
指向函数的指针以便提供该操作符的替代实现例如缺省的unique()利用容器的底层元
素类型的等于操作符来比较两个相邻的元素但是如果底层元素类型没有提供等于操作
920附录泛型算法
符或者我们希望定义不同的元素相等语义那么可以传递一个函数的对象或指向函数的指
针然后再由该函数提供期望的语义然而另外一些算法被分成两个不同名字的实例其
中第二个版本的实例都有后缀_if比如find_if()例如有一个使用内置等于操作符的
replace()实例和一个带有函数对象或函数指针的replace_if()实例
对那些修改所操作容器的算法一般有两个版本一个是实地in-place版本改变当
前正被应用的容器而在另一个版本中将返回容器的一个拷贝所做的修改被应用在这份
拷贝上例如有replace()和replace_copy()两个算法拷贝版本在名字中总会有_copy但
是并不是每一个要改变相关容器的算法都有拷贝版本例如sort()算法就没有提供拷贝版
本在这种情况下如果我们希望该算法在拷贝上进行操作则需要自己做一份拷贝并传
递给算法
要使用泛型算法我们必须包含相关的头文件
#include
如果要使用以下四个算术算法adjacent_difference()accumulate()inner_product()以及
partial_sum()则必须包含
#include
本附录中实现算法的代码以及这些算法所操作的容器类型反映了当前可用的标准库实
现iostream库反映了标准C++之前的实现版本例如包括使用iostream.h头文件这样
的行为在模板机制中模板参数不支持缺省实参为了使程序能在读者当前的系统上运行
或许需要修改某些声明
在[MUSSER96]我们可以找到关于泛型算法更完美更详细的讨论虽然对于最终
的C++标准库而言这些讨论有些过时
accumulate()
template
Typeaccumulate(
InputIteratorfirst,InputIteratorlast,
Typeinit);
template classBinaryOperation> Typeaccumulate( InputIteratorfirst,InputIteratorlast, Typeinit,BinaryOperationop); accumulate()的第一个版本把由iterator对[first,last)标记的序列中的元素之和加到一 个由init指定的初始值上例如已知序列{1,1,2,3,5,8}和初始值0则结果是20在第二个 版本中不再是做加法而是传递进来的二元操作被应用在元素上例如如果向accumulate() 传递函数对象times 一个算术算法要使用它我们必须包含 #include #include 921附录泛型算法 #include #include /* *输出为: accumulate() operatingonvalues{1,2,3,4} resultwithdefaultaddition: 10 resultwithplus 10 */ intmain() { intia[]={1,2,3,4}; list intia_result=accumulate(&ia[0],&ia[4],0); intilist_res=accumulate( ilist.begin(),ilist.end(),0,plus cout<<"accumulate()\n\t" <<"operatingonvalues{1,2,3,4}\n\t" <<"resultwithdefaultaddition: " < <<"resultwithplus " < < } adjacent_difference() template OutputIteratoradjacent_difference( InputIteratorfirst,InputIteratorlast, OutputIteratorresult); template classBinaryOperation> OutputIteratoradjacent_difference( InputIteratorfirst,InputIteratorlast, OutputIteratorresult,BinaryOperationop); adjacent_differece()的第一个版本创建了一个新的序列该序列中的每个新值第一个元 素除外都代表了当前元素与上一个元素的差例如已知序列{0,1,1,2,3,5,8}则新序列 的第一个元素只是原来序列第一个元素的拷贝0第二个元素是前两个元素的差1第三 个元素是第二个和第三个元素的差即1-1为0等等新序列是{0,1,0,1,1,2,3} 第二个版本用指定的二元操作计算相邻元素的差例如使用同一个序列让我们传递 times 个元素是原来第一个和第二个元素的积也是0第三个元素是第二和第三个元素的积即 922附录泛型算法 1*1为1等等新序列是{0,0,1,2,6,15,40} 在两个版本中OutputIterator总是指向新序列末元素的下一个位置adjacent_difference() 是一种算术算法使用这两个版本都必须包含头文件 #include #include #include #include #include intmain() { intia[]={1,1,2,3,5,8}; list list adjacent_difference(ilist.begin(),ilist.end(), ilist_result.begin()); //输出为: //101123 copy(ilist_result.begin(),ilist_result.end(), ostream_iterator cout< adjacent_difference(ilist.begin(),ilist.end(), ilist_result.begin(),times //输出为: //11261540 copy(ilist_result.begin(),ilist_result.end(), ostream_iterator cout< } adjacent_find() template ForwardIterator adjacent_find(ForwardIteratorfirst,ForwardIteratorlast); template ForwardIterator adjacent_find(ForwardIteratorfirst, ForwardIteratorlast,Predicatepred); adjacent_find()在由[first,last)标记的元素范围内查找第一对相邻的重复元素如果找到 则返回一个ForwardIterator并指向这对元素的第一个元素否则返回last例如已知序列 {0,1,1,2,2,4}元素对{1,1}被找到函数返回指向第一个1的iterator #include #include 923附录泛型算法 #include #include classTwiceOver{ public: booloperator()(intval1,intval2) {returnval1==val2/2? true: false;} }; intmain() { intia[]={1,4,4,8}; vector int*piter; vector : iteratoriter; //piter指向ia[1] piter=adjacent_find(ia,ia+4); assert(*piter==ia[1]); //iter指向vec[2] iter=adjacent_find(vec.begin(),vec.end(),TwiceOver()); assert(*iter==vec[2]); //到达这里表示一切顺利 cout<"ok: adjacent-find()succeeded! \n"; } binary_search() template bool binary_search(ForwardIteratorfirst, ForwardIteratorlast,constType&value); bool binary_search(ForwardIteratorfirst, ForwardIteratorlast,constType&value, Comparecomp); binary_search()在由[first,last)标记的有序序列中查找value如果找到则返回true否 则返回false第一个版本假设该容器是用底层类型的小于操作符排序的在第二个版本中 我们指出了该容器是用指定的函数对象进行排序的 #include #include #include intmain() { intia[]={29,23,20,22,17,15,26,51,19,12,35,40}; sort(&ia[0],&ia[12]); boolfound_it=binary_search(&ia[0],&ia[12],18); assert(found_it==false); 924附录泛型算法 vector sort(vec.begin(),vec.end(),greater found_it=binary_search(vec.begin(),vec.end(), 26,greater assert(found_it==true); } copy() template OutputIterator copy(InputIteratorfirst1,InputIteratorlast, OutputIteratorfirst2); copy()把由[first,last)标记的序列中的元素拷贝到由first2标记为开始的地方它返回 first2但此时first2已经被移动到最后一个插入元素的下一位置例如已知序列{0,1,2,3,4,5} 我们可以用下列调用将序列左移1位 intia[]={0,1,2,3,4,5}; //左移1位,结果为{1,2,3,4,5,5} copy(ia+1,ia+6,ia); copy()从ia的第二个元素开始把1拷贝到第一个位置上直到所有元素都被拷贝 到它左边的位置上 #include #include #include #include /*生成: 01135813 将数组序列左移1位 113581313 将vector序列左移2位 135813813 */ intmain() { intia[]={0,1,1,3,5,8,13}; vector ostream_iterator cout<<"originalelementsequence: \n"; copy(vec.begin(),vec.end(),ofile);cout<<'\n'; //左移1位 copy(ia+1,ia+7,ia); cout<<"shiftingarraysequenceleftby1: \n"; copy(ia,ia+7,ofile);cout<<'\n'; 925附录泛型算法 //左移2位 copy(vec.begin()+2,vec.end(),vec.begin()); cout<<"shiftingvectorsequenceleftby2: \n"; copy(vec.begin(),vec.end(),ofile);cout<<'\n'; } copy_backward() template classBidirectionalIterator2> BidirectionalIterator2 copy_backward(BidirectionalIterator1first, BidirectionalIterator1last1, BidirectionalIterator2last2); copy_backward()除了元素以相反的顺序被拷贝外其他行为与copy()相同也就是说 拷贝操作从last-1开始直到first这些元素也被从后向前拷贝到目标容器中从last2-1开 始一直拷贝last1-first个元素 例如已知序列{0,1,2,3,4,5}我们可以把最后三个元素(3,4,5)拷贝到前三个(0,1,2) 中做法是把first设为值0的地址last1设为值3的地址而last2设为值5的后一个位 置值为5的元素被赋给前面值为2的元素而元素4被赋给前面值为1的元素最后元 素3被赋给前面值为0的元素结果序列是{3,4,5,3,4,5} #include #include #include #include classprint_elements{ public: voidoperator()(stringelem){ cout< <<(_line_cnt++%8? "": "\n\t"); } staticvoidreset_line_cnt(){_line_cnt=1;} private: staticint_line_cnt; }; intprint_elements: : _line_cnt=1; /*生成: 原字符本为: Thelightuntonsuredhairgrainedandhuedlike paleoak 926附录泛型算法 copy_backward(begin+1,end-3,end)后的序列为: Thelightuntonsuredhairlightuntonsuredhairgrained andhued */ intmain() { stringsa[]={ "The","light","untonsured","hair", "grained","and","hued","like","pale","oak"}; vector cout<<"originallistofstrings: \n\t"; for_each(svec.begin(),svec.end(),print_elements()); cout<<"\n\n"; copy_backward(svec.begin()+1,svec.end()-3,svec.end()); print_elements: : reset_line_cnt(); cout<<"sequenceafter" <<"copy_backward(begin+1,end-3,end): \n"; for_each(svec.begin(),svec.end(),print_elements()); cout<<"\n"; } count() template iterator_traits : distance_type count(InputIteratorfirst, InputIteratorlast,constType&value); count()利用等于操作符把[first,last)标记范围内的元素与value进行比较并返回容器 中与value相等的元素的个数[注意标准库的实现支持早期的count()版本] #include #include #include #include #include #include #include /************************************************************** *textread: AliceEmmahaslongflowingredhair.HerDaddysays whenthewindblowsthroughherhair,itlooksalmostalive, likeafierybirdinflight.Abeautifulfierybird,hetellsher, 927附录泛型算法 magicalbutuntamed."Daddy,shush,thereisnosuchthing," shetellshim,atthesametimewantinghimtotellhermore. Shyly,sheasks,"Imean,Daddy,isthere? " **************************************************************** *程序输出: *count(): fieryoccurs2times **************************************************************** */ intmain() { ifstreaminfile("alice_emma");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 附录