C++标准模板库-STL库基本算法

jopen 9年前

16.4  STL库基本算法

标准C++STL库中算法组件为一个很重要的组成部分,该组件提供了大多数最常见的通用算法的实现,并且这些实现是经过很多测试试验并被公认在处理上是高效的。将这些最常见的算法通用化实现,最大的优势就是开发者在应用中不需要为具体的常见算法的实现而费神,只需要包含相应的头文件直接使用即可,不仅仅提高的软件开发的效率,同时还有助于软件重用性的提高。

16.4.1  STL库基本算法简介

根据STL标准库提供的文档,该库中的算法组件主要由于4个部分组成,即通用算法的实现划分为4类,分别应用对不同需求下的处理。

按照不同的特征处理划分第一类算法称之为非修正算法,其实就是提供的算法实现中不会涉及修改对应操作的容器中的任何元素,包括其位置等操作。这类算法主要为一些查找、统计、比较类操作实现,主要包含find()find_first()find_end()count()equal()等不需要进行操作的容器元素变动的算法。

第二类自然是与之对应的修正类算法,该类算法是在实际使用与具体的容器上时,需要通过适当的改变容器中内容从而实现相应的功能。这类针对容器处理需要修该的算法主要包括一些交换元素、替换元素、删除等操作实现,STL中主要包含copy()swap()remove()以及replace()等算法实现。

第三类自然是平时实际应用中较频繁的排序算法的提供,排序算法在实际应用中尤其是大数据量处理的软件中应用尤其突出,算法的处理效率适用场合决定着软件处理大数据量排序时的处理效率。STL库中针对排序提供了比较完备的算法实现,其中sort()table_sort()等算法都以较高处理效率而著称。

最后一类是针对容器中元素的计算提出的数值计算算法,主要提供了容器内元素乘积之和、元素加法之和以及相邻的元素之差等算法基本操作。

STL标准库提供的通用算法实现基本都是高效稳定的,对于初学者来讲理解这些不同类算法的基本实现功能、基本操作应用,另外需要了解的即在应用开发中遇到问题时会分析从而采用最适合的算法来解决相应的问题即可。随着逐步深入学习,为了更加理解相应库算法的具体实现,从而更好地利好用STL库中算法,可以逐步的学会分析该库提供的算法组件实现的源码,从中获取组件设计实现的思路,提高编程修养。

下面将会按照算法组件中4个类别的算法,分为4个小节对应着讲述STL库算法组件提供的算法操作基本实现原理,以及在实际应用中使用方法,初学者可以参照并在实践中尽可能的思考更多的应用情况。另由于STL库提供的算法约70多种之多,篇幅限制的情况下会根据不同类别的算法挑部分作为典型作详细的讲述,其它类别的算法可以采用触类旁通根据演示的基本使用方式,从而掌握其应用。

16.4.2  非修正算法

通过前面介绍STL库中算法组件提供了不需要修改容器内元素的算法操作实现,算法组件中非修正算法主要包括了adjacent_find()find()find_end()find_first()count()equal()for_each()以及serch()等操作接口。

这类算法操作主要针对不需要修改容器序列操作的情况下提供的,其中最常见的要算在容器之上的查找操作了。STL算法组件针对查找操作提供了几种不同的操作算法接口,分别为adjacent_find()find()find_end()find_first()

其中adjacent_find()算法操作主要用于查找容器中是否存在相邻元素,该方法接口返回找到的一对容器中指向相同临近元素之一的迭代器,该方法需要提供操作容器的范围迭代器。

find()操作算法主要用于查找容器中某个特定元素,找到则返回该容器中第一个找到特殊元素位置的迭代器。同时通过find()算法,可以根据需要扩展出多个如find_end()find_first()find_first_of()等算法操作接口,分别在find()算法基础上增加不同的限制实现的算法操作接口。

同时修正类算法还提供如equal()这样比较容器对象的算法操作,允许使用同类型容器不同对象之间比较,内部实际实现了不同的对象比较运算,以及for_each()算法在迭代器指定范围内循环执行相应参数提供的方法的操作,供实际应用中使用。下面将会通过一个完整实例,演示部分非修正算法的使用情况,通过这部分算法接口的操作应用了解STL库算法组件的常见使用方法。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter1613.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

实例chapter1613

源文件chapter1613.cpp

非修正类算法应用实例

*/

#include <iostream>

#include <algorithm>

#include <vector>

using namespace std;

 

int main()

{

//第一部分代码

         vector<int>testVector;                                            //定义int整型类型vector容器testVector

         vector<int>::iteratorfirstIter;                                   //定义int整型类型迭代器firstIter

         vector<int>::iteratorendIter;                                   //定义int整型类型迭代器endIter

         vector<int>::iteratortempIter;                                //定义int整型类型迭代器tempIter

         for(inti = 0;i < 10;i++)                                              //通过循环控制结构,变量i值从010循环10

         {

                   testVector.push_back(i);                               //通过容器提供的push_back方法将i变量值放入testVector

         }

         //find()算法演示

         firstIter= testVector.begin();                         //通过begin()方法将容器testVector首个元素赋值firstIter指向

         endIter= testVector.end();                                     //通过end()方法将容器testVector末元素赋值endIter指向

         tempIter  = find(firstIter,endIter,8);            //通过find()方法从容器首元素到尾元素之间查找元素值为8的元素

         if(tempIter== testVector.end())                   //判断是否遍历至容器尾部

         {

                   cout<<"Don'tfind element value's 8!"<<endl;    //提示没有找到相应元素

         }

         else

                   cout<<"Findthis element:"<<*tempIter<<endl;  //提示找到相应元素
//第二部分代码

         //adjacent_find()算法演示

         testVector.insert(++firstIter,2,10);                //通过insert()方法向容器testVector中插入元素值

         cout<<"vectorelements:";                             //提示打印输出容器元素

         for(firstIter= testVector.begin();firstIter != testVector.end();firstIter++)         //循环遍历容器testVector

         {

                   cout<<*firstIter<<"";                              //输出迭代器指向元素值

         }

         cout<<endl;

         firstIter= testVector.begin();                         //通过begin()方法将容器testVector首个元素赋值firstIter指向

         endIter   = testVector.end();                       //通过end()方法将容器testVector末元素赋值endIter指向

         tempIter= adjacent_find(firstIter,endIter); //通过adjacent_find()方法查找相邻相同元素

         if(tempIter!= testVector.end())                     //判断是否遍历至容器尾部

         {

                   cout<<"Findpair elements:"<<"("                         //找到则输出提示

                            <<*tempIter<<","<<*(tempIter+1)<<")"

                            <<"atloc:"<<tempIter - firstIter<<endl;

         }

         else

                   cout<<"notfind pair elements!"<<endl;               //未找到,输出提示

//第三部分代码

         //count()算法演示

         firstIter= testVector.begin();                         //通过begin()方法将容器testVector首个元素赋值firstIter指向

         endIter   = testVector.end();                       //通过end()方法将容器testVector末元素赋值endIter指向

         cout<<"countelement's 10:"<<count(firstIter,endIter,10)<<endl;        //通过count方法计算容器中元素10的个数

         return0;

}

2.编辑makefile

Linux平台下需要编译源文件为chapter1613.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter1613.o

CC=g++

 

chapter1613: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter1613

clean:

         rm-f chapter1613 core $(OBJECTS)

submit:

         cp-f -r chapter1613 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。在编译命令部分-g选项的加入,表明程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter1613.o chapter1613.cpp

g++ chapter1613.o -g -o chapter1613

[developer @localhost src]$ make submit

cp -f -r chapter1613../bin

[developer @localhost src]$ cd ../bin

[developer @localhost bin]$ ./chapter1613

Find this element:8

vector elements:0 10 10 1 2 3 4 5 6 7 8 9

Find pair elements:(10,10)at loc:1

count element's 10:2

4.剖析程序

本实例程序主要演示了非修正算法中find()adjacent_find()以及count算法接口的操作应用。STL库中算法组件通过头文件#include<algorithm>包含,即可以在应用程序中使用提供的相应的算法接口操作。

第一部分代码在主程序中只要定义整型空的序列容器vector对象testVector,随后定义三个该类型的迭代器分别表示指向容器首位置、尾位置以及作为临时结果的迭代器。

随后的for循环控制结构中,通过push_back方法向向量容器尾部循环添加对应的元素,将定义的两个迭代器通过容器提供的begin()end()方法分别定位到vector容器的首部和尾部。随后直接调用算法操作接口find(),该算法接口共三个参数,两个迭代器分别表示所要查找的元素区间,最后一个参数则表示所要查找的元素值。该方法调用中迭代器定位至容器首部与尾部,同时查找元素为整型值8,调用返回找到元素的指向迭代器,将其结果赋给结果迭代器tempIter

调用find方法之后将方法结果返回值赋给结果迭代器tempIter,之后判断该迭代器,并根据该结果迭代器的判断情况来说明是否找到相应的元素,以及通过解引用直接打印输出找到的元素。由于元素8存在于容器队列testVector中,if判断条件不成立,直接打印输出找到的元素值。

第二部分代码主要演示adjacent_find方法查找相邻相同元素,首先通过testVector调用insert方法在指定的首部之后的元素位置插入2个值为10的元素。此时通过迭代器firstIter遍历容器并打印输出容器中的内容为“0 10 10 1 2 3 4 5 6 7 8 9”。

随后迭代器firstIterendIter重新定位至容器的首部与尾部,通过调用adjacent_find方法演示相邻相同元素查找的算法操作,该算法接口主要包含两个参数,分别为需要查找的元素范围迭代器。程序中传入重新定位的两个迭代器,即表明查找操作将会在该容器的首部到尾部区间之间进行。由于该方法将会返回指向相邻相同元素的一个迭代器,将该方法结果直接赋给结果迭代器tempIter,随后开始判断该迭代器是否指向了容器的尾部,如果指向尾部则说明没找到相邻相同的元素,如果没有则打印相邻的两个元素值以及该元素所处的位置。

第三部分代码演示非修正算法中count统计序列相同元素个数的算法操作,将迭代器重新定位后,直接在流输出中调用count方法查找元素为10的个数,统计范围自然为从容器首部到尾部区间。

16.4.3  修正算法

STL库中修正算法主要针对数据元素序列处理可能涉及修改的情况,主要包括序列中元素的填充、交换、拷贝、删除与替换等。部分修正算法可以通过表格16.6作一个简单的说明,如下所示。

表格16.6  STL部分修正算法简介

算法接口

说明

fill(firstIter,endIter,value)

将元素值value填补到迭代器所指向区间中

copy(firstiter,endIter,firstIter1)

将迭代器firstIterendIter区间元素拷贝至迭代器firstIter1所指向的序列的开始之处

copy_backward(firstIter,endIter,firstIter1)

将迭代器firstIterendIter区间元素拷贝至迭代器firstiter1所指向的序列开始之初,但是从最后一个元素往前逐个拷贝赋值

remove(firstIter,endIter,value)

删除迭代器firstIterendIter区间内值为value的所有元素

replace(firstIter,endIter,value1,value2)

区间firstIterendIter之间元素,用value1替换所有的value2

reverse(firstIter,endIter)

将迭代器区间firstIterendIter之间的元素反向排列

swap(iter1,iter2)

交换迭代器iter1iter2所指向的元素

unique(firstIter,endIter)

去除迭代器firstIterendIter区间内重复的相邻元素

上述表格大致列出了STL库中修正类算法常用的几个算法操作,并作了简单的操作说明。修正类算法主要针对序列中删除、修改、交换等操作作了高效算法的实现,下面将会通过一个完整操作修正类算法的实例,根据STL中提供的算法的基本接口配合简单的说明在实际程序中应用这些算法。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter1614.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

实例chapter1614

源文件chapter1614.cpp

修正算法应用实例

*/

#include <iostream>

#include <algorithm>

#include <vector>

using namespace std;

 

int main()

{

//第一部分代码

         vector<int>testVector;                         //定义int整型类型vector容器对象testVector

         vector<int>::iteratorfirstIter;                //定义int整型类型容器迭代器firstIter

         vector<int>::iteratorendIter;                //定义int整型类型容器迭代器endIter

         for(inti = 0;i < 10;i++)                           //循环控制结构,从变量i0开始到10,循环10

         {

                  testVector.push_back(i);            //通过push_back将元素值i放入容器testVector

         }

         cout<<"vectorelements:";                   //提示打印输出容器内容

         for(firstIter= testVector.begin();firstIter != testVector.end();firstIter++)         //通过for循环控制遍历容器内容

         {

                   cout<<*firstIter<<"";                    //输出迭代器指向元素值

         }

         cout<<endl;

         firstIter= testVector.begin();                //通过begin()将容器testVector首元素赋值给firstIter指向

         endIter   = testVector.end();              //通过end()将容器testVector首元素赋值给endIter指向

         fill(firstIter,firstIter+3,8);                        //通过fill()方法在容器指定位置填充元素值8

         cout<<"vectorelements:";                   //提示输出容器内容

         for(firstIter= testVector.begin();firstIter != testVector.end();firstIter++)         //通过for循环遍历容器

         {

                   cout<<*firstIter<<"";                    //打印输出迭代器指向值

         }

         cout<<endl;

//第二部分代码

         firstIter= testVector.begin();                //通过begin()将容器testVector首元素赋值给firstIter指向

         endIter   = testVector.end();              //通过end()将容器testVector首元素赋值给endIter指向

         reverse(firstIter,endIter);                      //通过reverse()方法颠倒容器中的元素

      cout<<"vector elements:";                   //提示输出容器内容

      for(firstIter = testVector.begin();firstIter!= testVector.end();firstIter++)         //通过for循环遍历容器

     {

            cout<<*firstIter<<"";                    //打印输出迭代器指向值

     }

     cout<<endl;

//第三部分代码

     endIter =unique(testVector.begin(),testVector.end());        //通过unique()方法过滤相邻相同元素

     cout<<"vector elements:";                                                         //提示输出容器内容

     for(firstIter = testVector.begin();firstIter !=endIter;firstIter++)      //通过for循环遍历容器

     {

            cout<<*firstIter<<"";                    //打印输出迭代器指向值

     }

     cout<<endl;

         return0;

}

2.编辑makefile

Linux平台下需要编译源文件为chapter1614.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter1614.o

CC=g++

 

chapter1614: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter1614

clean:

         rm-f chapter1614 core $(OBJECTS)

submit:

         cp-f -r chapter1614 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。在编译命令部分-g选项的加入,表明程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter1614.o chapter1614.cpp

g++ chapter1614.o -g -o chapter1614

[developer @localhost src]$ make submit

cp -f -r chapter1614../bin

[developer @localhost src]$ cd ../bin

[developer @localhost bin]$ ./chapter1614

vector elements:0 1 2 3 4 5 6 7 8 9

vector elements:8 8 8 3 4 5 6 7 8 9

vector elements:9 8 7 6 5 4 3 8 8 8

vector elements:9 8 7 6 5 4 3 8

4.程序剖析

本实例主要演示了STL算法组件中fill()reverse()以及unique()三个方法操作应用,三个方法分别表示针对当前序列的填充、颠倒序列元素以及清除序列中相邻的同元素操作。

第一部分代码与前面实例相同首先定义空整型向量对象testVector,以及两个同等类型的迭代器分别表示区间头与尾。采用for循环结构向该容器中填入010的整型数据,随后通过迭代器遍历访问该容器序列并打印输出。随后将迭代器定位,firstIterenditer两个迭代器分别指向容器首部和尾部。调用算法组件中的fill方法,区间参数为firstIter所指位置到往后3个元素的位置处,填充值为8的元素。并且随后打印输出验证结果,容器序列中前3个元素被值为8的元素填充替换,此时的序列为“8 8 8 3 4 5 6 7 8 9”。

第二部分代码重新定位迭代器位置,调用reverse方法颠倒序列中的元素,参数区间为整个容器从首部到尾部之间。此时打印输出验证容器序列中的元素因为调用reverse方法而发生颠倒,序列为“9 8 7 6 5 4 3 8 8 8”。

第三部分代码算法演示则调用unique算法,去除了容器中相邻相同的元素,调用该方法直接传入容器调用beginend方法返回的迭代器区间参数,表明将在整个容器的首部与尾部来作该操作,打印输出验证,此时序列中的元素为“9 8 7 6 5 4 3 8”,相邻重复的元素8被删除只剩下一个。

16.4.4  排序算法

STL组件针对排序提供了超过20多种之多的算法实现,通常应用程序处理大数据量中排序算法的选择应用也是最普遍的。由于该类算法种类庞杂而多,下面将会通过介绍几种最常用的排序算法操作,从而了解算法组件中排序算法的一般操作规律。

排序算法中比较重要的几类算法包括sort()stable_sort()以及partial_sort()。其中sort算法原型为sort(firstIter,endIter),主要按照规定排序迭代器firstIterenditer区间内的元素。stable_sort算法同样拥有sort操作两个参数,但是该算法保持序列中相等元素的相对位置,从而减少因为移动而带来的处理时间消耗。

partial_sort算法原型为partial_sort(firstIter,midIter,endIter),主要排序的元素区间为firstIterendIter之间,将排序好的部分元素首先放置到firstItermidIter之间,其余未经过排序的部分放置到midIterendIter之间。

下面将通过完整实例演示其中sort()partial_sort()算法操作的应用情况,根据不同的需求从而选择不同的算法调用,实例中依然采用向量容器作为基本序列操作的对象。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter1615.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

实例chapter1615

源文件chapter1615.cpp

排序算法应用实例

*/

#include <iostream>

#include <algorithm>

#include <vector>

using namespace std;

 

int main()

{

//第一部分代码

         vector<int>testVector;                         //定义int整型类型vector容器对象testVector

         vector<int>::iteratorfirstIter;                //定义int整型类型迭代器firstIter

         vector<int>::iteratorendIter;                //定义int整型类型迭代器endIter

         testVector.push_back(2);                    //通过push_back()方法将元素2放入容器

         testVector.push_back(3);                    //通过push_back()方法将元素3放入容器

         testVector.push_back(1);                    //通过push_back()方法将元素1放入容器

         testVector.push_back(6);                    //通过push_back()方法将元素6放入容器

         testVector.push_back(8);                    //通过push_back()方法将元素8放入容器

         testVector.push_back(10);                  //通过push_back()方法将元素10放入容器

         cout<<"vectorelements:";                   //提示输出容器内容

     for(firstIter = testVector.begin();firstIter !=testVector.end();firstIter++)         //通过循环遍历容器

     {

            cout<<*firstIter<<"";                    //输出迭代器指向内容

     }

     cout<<endl;
//
第二部分代码

     firstIter = testVector.begin();                //通过begin()方法将容器testVector首元素赋值给firstIter指向

     endIter  = testVector.end();              //通过end ()方法将容器testVector首元素赋值给endIter指向

     sort(firstIter,endIter);                             //通过sort()方法对容器元素进行排序

     cout<<"vector elements:";                   //提示输出容器内容

     for(firstIter = testVector.begin();firstIter !=testVector.end();firstIter++)         //通过循环遍历容器

     {

            cout<<*firstIter<<"";                    //输出迭代器指向内容

     }

     cout<<endl;

//第三部分代码

     firstIter = testVector.begin();                //通过begin()方法将容器testVector首元素赋值给firstIter指向

     endIter  = testVector.end();              //通过end ()方法将容器testVector首元素赋值给endIter指向

     random_shuffle(firstIter,endIter);      //通过random_shuffle方法随机打乱容器内元素

     cout<<"vector elements:";                   //提示输出容器内容

     for(firstIter = testVector.begin();firstIter !=testVector.end();firstIter++)         //通过循环遍历容器

     {

            cout<<*firstIter<<"";                    //输出迭代器指向内容

     }

     cout<<endl;

     partial_sort(testVector.begin(),testVector.begin()+4,testVector.end());//通过partial_sort方法对容器排序

     cout<<"vectorelements:";                   //提示输出容器内容

     for(firstIter = testVector.begin();firstIter !=testVector.end();firstIter++)         //通过循环遍历容器

     {

            cout<<*firstIter<<"";                    //输出迭代器指向内容

     }

     cout<<endl;

         return0;

}

2.编辑makefile

Linux平台下需要编译源文件为chapter1615.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter1615.o

CC=g++

 

chapter1615: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter1615

clean:

         rm-f chapter1615 core $(OBJECTS)

submit:

         cp-f -r chapter1615 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。在编译命令部分-g选项的加入,表明程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter1615.o chapter1615.cpp

g++ chapter1615.o -g -o chapter1615

[developer @localhost src]$ make submit

cp -f -r chapter1615../bin

[developer @localhost src]$ cd ../bin

[developer @localhost bin]$ ./chapter1615

vector elements:2 3 1 6 8 10

vector elements:1 2 3 6 8 10

vector elements:8 6 2 3 1 10

vector elements:1 2 3 6 8 10

4.程序剖析

本实例主要演示了vector容器中操作排序基本算法的方法,下面将会将代码分为三个部分进行分析。

第一部分代码实例中定义空的整型向量对象testVector,同时定义两个迭代器分别表示容器首尾。随后通过调用其push_back方法,在容器尾部添加不同的元素。此时容器中的元素序列根据迭代器遍历打印输出结果为“2 3 1 6 8 10”。

第二部分代码将两个迭代器分别定位到向量testVector首部与尾部位置,调用sort算法操作排序参数区间的元素,其排序结果打印输出为“1 2 3 6 8 10”。默认情况下sort算法操作按照升序方式排序序列中的元素,当然也可以通过第三个参数来指定排序方式。

第三部分代码首先通过random_shuffle方法将首尾迭代器之间的元素进行随机排列,之后演示partial_sort算法操作,其传入的第一个参数为testVector向量首部元素的迭代器,第二个参数则指定为指向首部元素向后挪4个位置的迭代器表示中间位置,第三个参数则为指向向量尾部的迭代器。跟据该算法操作的基本描述,该方法应该将已经排序的元素放入中间迭代器位置之前,未排序的则放置之后。最后通过迭代器遍历打印输出结果验证,该容器中结果为“1 2 3 6 10 8”,此时从第4个元素位置开始前面都是已经排序的元素,而从第4个元素之后两个元素则未排序。

16.4.5  数值算法

STL标准库算法组件针对数值处理提供了4个算法实现,分别为accumulate()inner_product()partial_sum()以及adjacent_difference()。四个算法基本原型与接口说明如表格16.7所示。

表格16.7 STL标准库数值算法接口说明

算法接口

说明

accumulate(firstIter,endIter,value)

计算序列中从firstIterendIter区间内每个元素与value之和

inner_product(firstIter,endIter,firstIter1,value)

计算序列中value与从firstIterendIter区间内每个元素与firstIter1所指范围内元素乘积之和

partial_sum(firstIter,enditer,result)

计算迭代器firstiterenditer区间中元素的部分之和,结果放入result中,即该区间的第一个元素作为结果result第一个元素,随后前面相邻两个元素相加作为第二个元素,以此递归下去

adjacent_difference(firstIter,endIter,result)

同上描述,仅仅是计算了元素相邻差而已

下面将会通过实例演示4种数值算法在应用程序中的实际使用方式,实例如下所示。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter1616.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

实例chapter1616

源文件chapter1616.cpp

数值算法应用实例

*/

#include <iostream>

#include <numeric>

#include <vector>

using namespace std;

 

int main()

{

//第一部分代码

         vector<int>testVector;                         //定义int整型类型vector容器对象testVector

         vector<int>testVector1(6);                  //定义int整型类型vector容器对象testVector1

         vector<int>::iteratorfirstIter;                //定义int整型类型迭代器firstIter

         vector<int>::iteratorendIter;                //定义int整型类型迭代器endIter

         vector<int>::iteratortempIter;              //定义int整型类型迭代器tempIter

         testVector.push_back(2);                    //通过push_back方法将元素2放入容器testVector

         testVector.push_back(3);                    //通过push_back方法将元素3放入容器testVector

         testVector.push_back(1);                    //通过push_back方法将元素1放入容器testVector

         testVector.push_back(6);                    //通过push_back方法将元素6放入容器testVector

         testVector.push_back(8);                    //通过push_back方法将元素8放入容器testVector

         testVector.push_back(10);                  //通过push_back方法将元素10放入容器testVector

         cout<<"vectorelements:";                   //提示输出容器内容

    for(firstIter= testVector.begin();firstIter != testVector.end();firstIter++)         //通过循环遍历容器元素

    {

    cout<<*firstIter<<"";                    //输出迭代器指向元素值

     }

    cout<<endl;

    firstIter= testVector.begin();                //通过begin()方法将容器testVector首元素赋值给迭代器firstIter

    endIter   = testVector.end();              //通过end ()方法将容器testVector首元素赋值给迭代器endIter

    intresult;                                                 //定义整型结果变量result

    result= accumulate(firstIter,endIter,2);      //通过accumulate方法计算容器内元素,同时计算元素2

    cout<<"result= "<<result<<endl;                 //输出该计算结果值

//第二部分代码

    firstIter= testVector.begin();                //通过begin()方法将容器testVector首元素赋值给迭代器firstIter

    endIter   = testVector.end();              //通过end ()方法将容器testVector首元素赋值给迭代器endIter

    result= inner_product(firstIter,endIter,firstIter+2,8);   //通过inner_product方法做容器元素内乘积计算

    cout<<"result= "<<result<<endl;        //输出容器乘积结果

//第三部分代码

    firstIter= testVector.begin();                //通过begin()方法将容器testVector首元素复制给迭代器firstIter

    endIter   =testVector.end();              //通过end()方法将容器testVector尾元素复制给迭代器endIter

    partial_sum(firstIter,endIter,testVector1.begin());       //通过partial_sum()方法将容器内元素实现迭代和计算

    cout<<"vectorelements:";                   //提示输出容器结果

    for(firstIter= testVector1.begin();firstIter != testVector1.end();firstIter++)    //通过循环遍历该容器内部元素

    {

    cout<<*firstIter<<"";                    //输出迭代器指向元素值

    }

    cout<<endl;

//第四部分代码

    firstIter= testVector.begin();                //通过begin()方法将容器testVector首元素复制给迭代器firstIter

    endIter   = testVector.end();              //通过end()方法将容器testVector尾元素复制给迭代器endIter

    adjacent_difference(firstIter,endIter,testVector1.begin()); //通过adjacent_difference方法实现容器元素迭减

    cout<<"vectorelements:";                   //提示输出计算结果

    for(firstIter= testVector1.begin();firstIter != testVector1.end();firstIter++)    //通过循环遍历该容器内部元素

    {

    cout<<*firstIter<<"";                    //输出迭代器指向元素值

    }

    cout<<endl;

    return0;

}

2.编辑makefile

Linux平台下需要编译源文件为chapter1616.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter1616.o

CC=g++

 

chapter1616: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter1616

clean:

         rm-f chapter1616 core $(OBJECTS)

submit:

         cp-f -r chapter1616 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。在编译命令部分-g选项的加入,表明程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter1616.o chapter1616.cpp

g++ chapter1616.o -g -o chapter1616

[developer @localhost src]$ make submit

cp -f -r chapter1616../bin

[developer @localhost src]$ cd ../bin

[developer @localhost bin]$ ./chapter1616

vector elements:2 3 1 6 8 10

result = 32

result = 96

vector elements:2 5 6 12 20 30

vector elements:2 1 -2 5 2 2

4.剖析程序

本实例演示了上述4种数值算法操作,分别为accumulateinner_productpartial_sumadjacent_difference。程序将会分为四个部分进行剖析讲解。

第一部分代码程序中首先定义两个vector向量对象,一个为空另一个为大小指定6个元素。随后将向量对象testVector调用push_back方法添加元素进入容器中,打印输出该容器中元素为“2 3 1 6 8 10”。

定位两个迭代器对象的位置为testVector容器的首部与尾部,同时定义整型变量result作为调用accumulate算法计算的结果。该算法中以区间firstIterendIter之间的元素累加并加上第三个元素值之和作为计算结果返回赋给result,打印输出该结果为32,内部实现“2+3+1+6+8+10+2”的计算。

第二部分代码将迭代器重新定位到testVector向量首尾部位置,随后调用inner_product方法根据传入的参数将计算结果赋值给result变量打印输出。由于计算区间为firstiterenditer之间,同时指定另一个参数为firstIter+2的位置开始往后的元素,两边元素相乘最后相加结果加上第四个元素值8。该算法内部计算为序列一“2 3 1 6 8 10”,序列二“1 6 8 10 0 0”,计算为“2*1+3*6+1*8+6*10+8*0+10*0+8”最后结果为96

第三部分代码算法操作partial_sum接口的调用中,参数区间为容器对象testVector首尾部迭代器指定的区间,第三个参数即计算结果则存放入另一个容器对象testVector1,所以该参数为指向该容器首部的迭代器。根据该方法算法描述,该操作将testVector中第一个元素作为结果容器中第一个元素,随后的每个元素都为前两个元素之和,即计算过程为第一个元素为“2”,随后“2+3”、“1+2+3”、“6+1+2+3”、“8+6+1+2+3”“10+1+2+3+6+8”,最后计算结果存放入容器testVector1中,打印输出该容器中内容结果为“2 5 6 12 20 30”。

第四部分代码partial_sum算法计算想反,adjacent_difference算法操作则将相邻两个元素相减的结果放入结果容器中,容器testVector中存放元素为“2 3 1 6 8 10”,调用该方法后计算结果容器中存放的元素为“2”、“3-2”、“1-3”、“6-1”、“8-6”、“10-8”,最后结果容器中打印输出序列为“2 1 -2 5 2 2”。

16.5  小结

STL标准库提供的内容主要分为六个部分,由于篇幅限制本书只向初学者介绍其中最常用的前三个部分。其中函数对象、内存分配器以及配接器随着深入学习模板部分编程时再逐步讲述。STL模板库包含内容非常的丰富,详细讲述需要通过一本书都介绍不完全部内容,本章的宗旨在于通过讲述其中部分常见模板库的应用情况,通过一些操作实例实践希望初学者能够掌握STL库一般使用方法,从而触类旁通进而掌握使用STL库的方法。