泛型算法与容器的关系
2016-08-28 10:40
176 查看
1.前言
c++中的容器支持插入删除操作,支持获取第一个元素的迭代器和超过元素末端的下一迭代器操作......但是却不支持获取指定元素操作,比较操作,排序操作......因为这些操作都是和算法有关的,在C++中将它们独立出来,说明算法和具体的容器和具体的数据类型无关,只和自身的元素相关。比如find函数,用于查找指定的值,看下面两段代码:vector<int> vect; //往vect添加元素 vector<int>::iterator iter=find(vect.begin(),vect,end(),search_value); list<int> lis; //添加元素 list<int>::iterator iter=find(lis.begin(),lis.end(),search_value); int a[5]={1,2,3,4,5}; int *result=find(a,a+5,search_value);
我们可以对于find函数来说,它对于容器的类型和数据类型都没有要求,即它只与自身的算法实现有关,和容器类型无关。除了迭代器之外,我们可以发现,指针也可以用于find函数的实参。所以对find函数来说只有几个要求:
①、数据类型必须是可以比较的,这样才可以判断是否是所查找的值。
②、必须给定一段范围,必须知道从哪里开始从哪里结束。
③、如果找到该值,就返回指向该值的指针或者迭代器,否则返回第二个参数即最后一个元素的下一个元素的地址。
在C++中提供了泛型算法,它包含在algorithm头文件中,以及一个泛化的算数算法,它包含在numeric头文件中。
2、只读算法
只读算法只会读取范围内的元素,而不对范围内的元素进行任何操作。前面的find函数就是一个例子,另一个就是accumulate函数,定义在numeric头文件中,它使用数据类型的加法操作进行将某段元素范围的元素相加。考虑下面的代码:vecotr<int> vectInt; vector<string> vectString; int sum=accumulate(vectInt.begin(),vectInt.end(),0); string result=accumulate(vectString.begin(),vectString.end(),string(""));
上述尝试对int和string元素进行相加操作,对于sum的值,它是以0为起始值,并把vectInt标记的元素范围内所有值的相加。对于accumulate来说,它并不知道要添加的元素的类型是什么,因此它是通过第三个参数来判断执行加操作符的意义的。比如result的结果则是,获取了一端拼接起来的字符串。注意这里不能替换为字符串字面值,因为字符串字面值是const char*类型,这样会导致编译错误。
在numeric头文件,还有很多find系列的函数,比如find_fisrt_of();此函数接受四个参数,分别标志两段数据范围,它的作用用于查找在这两段标志的区间里面重合的元素,如果找到了就返回第一段范围内第一个重合元素的迭代器,否则就返回第一段范围内最后一个元素的下一个元素的迭代器。看如下代码:
#include<iostream> #include<algorithm> #include<vector> using namespace::std; int main() { vector<string> vect; vect.push_back("harden"); vect.push_back("james"); vect.push_back("howard"); vect.push_back("harden"); vect.push_back("wade"); vector<string> vect1(vect); vect1.erase(--vect1.end()); vector<string>::iterator it = vect.begin(); int count = 0; while ((it = find_first_of(it, vect.end(), vect1.begin(), vect1.end())) != vect.end()) { count++; it++; } cout << count << endl; system("pause"); return 0; }
上述代码会打印出4,因为在第一段范围内,每次查找到第一个元素就会缩小到下一个元素,这样就把第一段范围内所有的与第二段范围重合的元素查找出来了。
3、利用算法排序元素
C++提供了排序算法,可用于排序容器内的元素,比如sort,此方法有两个版本,一个是接受一对迭代器作为实参(此版本的方法默认是使用<比较符比较对象),另外一个是除了一对迭代器之外,还接受一个函数名称。对该函数是由要求的,比如如果排序的对象是vector<int>型,则该函数的返回值必须是bool,形参必须是两个int型对象的引用。注意,任何算法都不会删除或修改添加容器元素的元素数据。因此C++还提供了一个unique算法,可以将所有容器中出现多次的内容都排到容器末端,并且返回指向第一个相同元素的迭代器。通过它,我们就可以避免重复对容器中相同的元素进行操作。
看下面的代码:
vector<string> vect; vect.push_back("harden"); vect.push_back("james"); vect.push_back("howard"); vect.push_back("harden"); vect.push_back("wade"); /* 对容器内元素进行排序 */ vect.push_back("james"); //sort 元素会对元素内的元素进行<排序 sort(vect.begin(), vect.end()); cout << "输出从小到大排序后的内容:"; for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it) { cout << *it<<" "; } cout << endl; //此函数会将容器内的元素的相同元素都排到容器的末端,然后返回指向第一个相同元素的迭代器。即在此迭代器之前的元素都是唯一的 vector<string>::iterator uniqu_end = unique(vect.begin(), vect.end()); cout<<"输出不包含相同元素的容器内容:"; for (vector<string>::iterator it = vect.begin(); it < uniqu_end; ++it) { cout << *it << " "; } cout << endl; //可使用erase将相同元素删掉。 vect.erase(uniqu_end, vect.end()); cout << "输出删除元素后的内容:"; for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it) { cout << *it << " "; } cout << endl; //使用sort的时候,也可以自带排序算法函数 sort(vect.begin(), vect.end(), isLonger); cout << "输出从大到小排序元素后的内容:"; for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it) { cout << *it << " "; } cout << endl;
isLonger函数如下:
bool isLonger(string &one, string &two) { return one > two; }
输出结果:
4.迭代器综述
我们一般接触的迭代器都是正向迭代器,其实C++还提供了正向迭代器,iostream迭代器,插入迭代器。如下:有关算法是不和容器捆绑的,除了前面提到的算法之外,还有很多不常用的算法,希望读者有兴趣的多去了解。
---------文章写自:HyHarden---------
--------博客地址:http://blog.csdn.net/qq_25722767-----------
相关文章推荐
- Spring和SpringMVC父子容器关系初窥
- 深入理解Java Servlet与Web容器之间的关系
- SERVLET容器简介与JSP的关系
- Servlet容器与Servlet,Tomcat的关系
- JSP学习 —— 开篇:JSP,servlet容器,Tomcat,servlet容器之间的关系
- 父子上下文的关系以及对子上下文容器中Action进行AOP(事务)的思想 (important)
- 侯捷STL学习(五)--allocator和容器之间的实现关系
- Spring在 IOC 容器中 Bean 之间的关系
- Spring和SpringMVC父子容器关系初窥
- 两层容器的position 之间的关系
- aop切面配置不起作用引发的spring容器和spring mvc容器关系学习
- jvm实例,tomcat容器,spring容器,在内存中的关系
- Spring和SpringMVC父子容器关系初窥
- spring中IOC容器创建对象,对象依赖关系处理
- Java常见容器(Container)关系图
- 学习淘淘商城第十课(SSM框架整合之springmvc整合及父子容器的关系)
- 两层容器的position 之间的关系
- 数组-应用(作为关系映射表,作为临时容器)
- 关于Web容器,servlet容器和web应用的关系
- 初学者对Servlet、JSP及Web容器之间关系的理解