STL学习记录(三):算法基础简要
2015-10-06 00:00
316 查看
STL算法基础简要
简单的算法实例算法中的范围(Ranges)
简单的算法实例
STL提供多种标准算法来处理容器中的数据,这些算法包括搜索、排序、拷贝、修改,重排等基本常用的操作。STL算法不是某个容器类的成员函数而是,通过迭代器操作的全局函数。这样的一个好处就是算法只需要实现一次,而不用为每个特定类型的容器都重新实现算法。它还支持用户自定义的容器类型。实例代码
常用版本 :#include <alogrithm> #include <vector> #include <iostream> using namespace std; int main(){ vector<int> coll; coll.push_back(2); coll.push_back(5); coll.push_back(4); coll.push_back(1); coll.push_back(6); coll.push_back(3); vector<int>::const_iterator minpos=min_element(coll.begin(),coll.end()); cout<<"min: "<<*minpos<<endl; vector<int>::const_iterator maxpos=min_element(coll.begin(),coll.end()); cout<<"max: "<<*maxpos<<endl; sort(coll.begin(),coll.end()); vector<int>::iterator pos3; pos3=find(coll.begin(),coll.end(),3); reverse(pos3,coll.end()); vector<int>::const_iterator pos; for(pos=coll.begin();pos!=coll.end();++pos){ cout<<*pos<<" "; } cout<<endl; return 0; }
C++11 版本:
#include <alogrithm> #include <vector> #include <iostream> using namespace std; int main(){ vector<int> coll={2,5,6,1,6,3}; auto minpos=min_element(coll.cbegin(),coll.cend()); cout<<"min: "<<*minpos<<endl; auto maxpos=min_element(coll.cbegin(),coll.cend()); cout<<"max: "<<*maxpos<<endl; sort(coll.begin(),coll.end()); auto pos3=find(coll.begin(),coll.end(),3); reverse(pos3,coll.end()); for(auto elem:coll){ cout<<elem<<" "; } cout<<endl; return 0; }
**程序的输出均为: **
min: 1
max: 6
1 2 6 5 4 3
实例中min_element() 和 max_element() 算法通过两个参数来确定算法的操作范围,算法返回的是一个iterator对象,分别指向最小值和最大值。find() 算法查找所给区域内的某个值,当找到是返回第一个该值的iterator 若没有则返回的是该区域内最后一个对象的下一个对象的 iterator 该例中是 coll.end()。sort() 算法对所给区域内的对象进行排序。 reverse()对所给区域内对象进行倒置。
##算法中的范围(Ranges)
每个算法处理的都是一个或者多个范围的数据元素。你通过两个语句将范围的开始和结尾传递给算法,而不是通过一个语句。这个接口很灵活但是同时也带来了一些问题,例如某个范围: list_1.begin() ,list_2.end() 那么当迭代器前进的时候,因为永远都无法到达范围的结尾程序将出现不可预知的问题。从这个角度来说迭代器并没有传统的指针那么安全可靠。所以在使用算法的时候,一定要确保迭代器属于同一个容器并且确保范围正确,不要将开始和结尾倒置了。当然这种错误导致的未定义行为,STL可以自行捕捉和并进行相应处理。
每个算法中的范围都是个半开区间,用数学中的定义就是左闭右开区间。所以该范围包含开始,但是不包含用于标识末尾的位置。这样的一个好处就是有效的防止了我们多余空容器的处理。
实例代码:
#include<iostream> #include<list> #include<algorithm> using namespaced std: int main(){ list<int> coll; for(int i=20;i<40;++i){ coll.push_back(i); } list<int>::iterator pos25,pos35; pos25=find(coll.begin(),coll.end(),25); pos35=find(coll.begin(),coll.end(),35); cout<<"max: "<<*max_element(pos25,pos35)<<endl; cout<<"max: "<<*max_element(pos25,++pos35)<<endl; return 0; }
输出结果:
max: 34
max: 35
需要注意的有:
针对本例中的不支持随机访问的容器迭代器前进采用 ++ 而像vector 这种支持随机访问的可以采用 +1
本例中我们事先就已经知道了pos25与pos35的前后关系当我们不知道两者的前后关系时该如何应对
支持随机访问容器的应对方法:
if(pos25<pos35){ //[pos25,pos35)为有效范围 } else{ //[pos35,pos25)为有效范围 }
不支持随机访问容器的常规应对方法:
pos25=find(cloo.begin(),coll.end(),25); pos35=find(coll.begin(),pos25,35); if(pos25!=coll.end() && pos35!=pos25){ //pos35在前面有效区间[pos35,pos25) } else{ pos35=find(pos25,coll.end(),35); if(pos!=coll.end(){ //pos25在前面有效区间[pos25,pos35) } else{ //pos25与pos35至少有一个不存在 } }
不支持随机访问容器的C++11中更加有效的方法:
pos=find_if(coll.begin(),coll.end(), [] (int i){ return i==25 || i==35; }); if(pos==coll.end()){ //不存在值为25和35的迭代器 .... } else if(*pos==25){ //25在前面 pos25=pos; pos35=find(++pos,coll.end(),35); .... } else { //35在前面 pos35=pos; pos25=find(++pos,coll.end(),25); .... }
在这段代码中使用了lambda表达式,这是c++11标准中才开始采用的。该表达式用来确定查找时返回第一个出现的值(25 or 35),如果存在的话。
[] (int i){ return i==25 || i==35; }
多个范围的处理
在某些算法中可能涉及到多个范围例如equal、copy函数,在使用这些算法的时候需要注意第二个范围的大小最起码等于第一范围的大小。当第二个范围小的时候我们需要重新设定第二个范围的大小。
#include<iostream> #include<list> #include<vector> #include<deque> using namespace std: int main(){ list<int> coll={1,2,3,4,5}; //c++11 vector<int> coll2; //重置coll2大小调用equal算法 coll2.resize(coll.size()); if(equal(coll1.begin(),coll1.end(),coll2.begin()){ cout<<"coll1 is equal coll2"<<endl; } deque<int> coll3(coll1.size());//让coll3与coll1大小一样 copy(coll1.begin(),coll1.end(),coll3.begin()); return 0; }
需要注意的是这里不管是重置大小还是初始化时就给定大小,其实都为容易创建了新的元素(元素的值由默认构造器初始化)。还有就是这里copy算法之所以需要第二个范围大是因为该算法采用重写的方式而不是插入。
相关文章推荐
- STL学习记录(四):Vector
- STL学习记录(八)Sets、Multisets
- STL学习记录(五):Deque
- STL学习记录(六):List
- STL学习记录(十一):修改类算法
- STL学习记录(九)Maps、Multimaps
- STL学习记录(十二):非修改类算法
- STL学习记录(十六):Queue、Priority Queue
- STL学习记录(十三):排序类算法及基于排序的算法
- STL学习记录(十四):其它几种算法
- STL学习记录(十五):Stack
- STL学习记录(七):Forward List
- STL学习记录(十):Iterator
- 调用时,加断言assert.h与自制打印消息的记录
- <errno.h>的简单使用
- PCL 室内三维重建
- App开发平台 80%的工作量交给keymob
- 最专业的移动广告开发平台 让您的广告布满世界的每一个角落
- 2015APP开发平台需要多少钱
- 移动广告服务平台 APP广告管理服keymob