STL区间成员函数及区间算法总结

在这里总结下可替代循环的区间成员函数和区间算法;

相比单元素遍历操作,使用区间成员函数的优势在于:
1)更少的函数调用
2)更少的元素移动
3)更少的内存分配

在区间成员函数不适用的情况下也应该使用区间算法,至少,相比手写循环而言,它更加简单,有效,并且不容易出错;

区间成员函数

区间构造

标准容器都支持区间构造函数:

container::container(InputIterator begin, // 区间的起点InputIterator end); // 区间的终点

例如:

int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8); 

以上是c++98中常用法,在C++11中,vector可以直接初始化了:

std::vector<int> second ={10, 20, 30, 30, 20, 10, 10, 20};
或者:
std::vector<int> second ({10, 20, 30, 30, 20, 10, 10, 20});   

区间插入

标准序列容器提供这种形式的insert:

void container::insert(iterator position, // 区间插入的位置InputIterator begin, // 插入区间的起点InputIterator end); // 插入区间的终点

例如:

int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector;
myvector.push_back(100);
myvector.insert(myvector.begin(),myints,myints+8); //10 20 30 30 20 10 10 20 100

关联容器也支持区间插入,但由于其插入后的位置由其比较函数来决定,所以没有区间插入的位置这个参数;

区间删除

标准序列容器提供的erase:

iterator container::erase(iterator begin, iterator end); 

c++98的标准关联容器提供的erase为:

void container::erase(iterator begin, iterator end);

序列容器调用erase之后,返回一个迭代器(被删除的那个元素的下一个),
而关联容器的erase删除之后并不返回迭代器.【官方解释说如果实现成序列容器那样返回指向下一个迭代器,会导致无法接收的性能下降】;

这一区别在c++11中终于统一了;c++11中,对关联容器调用erase之后会返回一个迭代器(指向被删除元素的下一个);

iterator container::erase(const_iterator first, const_iterator last);

区间赋值

所有标准容器提供了区间赋值的成员函数:

void container::assign(InputIterator begin, InputIterator end);

这个函数用于给容器赋值,会替代现有值,并根据需要分配空间;
与copy()算法的区别在于它不需要预先分配空间,并有更高的性能;

int myints[]={10,20,30,40,50,60,70};
std::vector<int> myvector;
myvector.assign(myints,myints+7);

通用区间算法

for_each 区间迭代

for_each:遍历,对每个元素都执行一个动作;
C++98只支持最原始的for循环,很多语言(java、python等)都实现了foreach区间迭代语法,这让C++程序员眼馋了很久;
在没有foreach区间迭代的时代,我们可以用for_each()算法来代替:

例:对每个元素都加5:

void myfunction (int& i) {i += 5;
}std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
for_each(myvector.begin(),myvector.end(),myfunction); //15 25 35

c++11中新增了区间迭代,使得我们对for_each的依赖降低了,使用也更加方便:

for(auto &i : myvector )
{i+=5;
}

transform() 区间迭代后新值另存为其它地方

对区间中每个元素执行操作后,将修改后的值写入到新区间中;
可以认为这个是for_each()算法不修改原区间的版本;
还是for_each中的例子:

int addfunction(int i ){return i+5;
}void output (int i) {  // output functionstd::cout << ' ' << i;
}std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
std::vector<int> bvector;
bvector.resize(myvector.size());
transform(myvector.begin(),myvector.end(),bvector.begin(),addfunction);
//输出
for_each(bvector.begin(),bvector.end(),output); //bvector: 15 25 35

copy() 区间复制

区间复制,一般用于多个容器间的数据传值;
这个算法被用的很普遍,其实,很多使用copy的场景,都可以使用区间成员函数来替代(也建议这么做);

例:复制数组到vector:

int myints[]={10,20,30,40,50,60,70};
std::vector<int> myvector (7);
std::copy ( myints, myints+7, myvector.begin() );

fill() 区间填充

用一个元素来重复填充区间;
这个算法使用频率较低;
例:用5填充vector前4个元素:

std::vector<int> myvector (8);                       // myvector: 0 0 0 0 0 0 0 0
std::fill (myvector.begin(),myvector.begin()+4,5);   // myvector: 5 5 5 5 0 0 0 0

replace() 区间替换

遍历区间,进行值替换:
例:将以下区间中所有20替换为99:

int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
std::replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99

更复杂的版本(使用仿函数)replace_if
例:将以下区间中所有大于20替换为99:

bool bigerThen20 (int i) { return i > 20; }int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
std::replace_if (myvector.begin(), myvector.end(), bigerThen20, 99); //10 20 99 99 20 10 10 20

由于用到了仿函数,通过replace_if实现的,用for_each()也很容易实现;

remove() 区间删除

从区间中删除指定元素;

int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
std::remove(myvector.begin(), myvector.end(), 20); // 10 30 30 10 10 ? ? ? 

注意,remove并不会真正删除元素,而只是将需要删除的元素放到到最后,同时返回一个新的尾部迭代器,
比如,上述例子中,调用完remove后,vector中的值一般为 //10 30 30 10 10 10 10 20
而如果希望真的删除元素,需要加上成员函数erase()来实现删除 【remove-erase惯用法】:

myvector.erase(std::remove(myvector.begin(), myvector.end(), 20),myvector.end()); // 10 30 30 10 10

unique() 区间去重

从区间中删除相邻相同的元素,同样,这个算法也不会真正的删除元素,而是将待删除的元素移到区间尾部;
使用【unique-erase惯用法】:

int myints[] = {10,20,20,20,30,30,20,20,10};           // 10 20 20 20 30 30 20 20 10
std::vector<int> myvector (myints,myints+9);
std::vector<int>::iterator it;
it = std::unique (myvector.begin(), myvector.end());   // 10 20 30 20 10 ?  ?  ?  ?
myvector.erase(it,myvector.end());

Posted by: 大CC | 28JUN,2015
博客:blog.me115.com [订阅]
微博:新浪微博

STL区间成员函数及区间算法总结相关推荐

  1. 2.区间成员函数优先于与之对应的单元素成员函数

    案例1:v1.v2两个vector, 将v2后半部分内容赋给v1 区间成员函数版本: std::vector<int> v1; ... std::vector<int> v2; ...

  2. STL vector成员函数详解

    一. 常用简单成员函数 vector::push_back(Type val) //将val添加到向量尾部 vector::pop_back() //将最后一个元素删除 iterator vector ...

  3. c++ hashset的用法_c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例

    c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. 1 ...

  4. 17.容器的成员函数优先于同名的算法

    有些STL 容器提供了一些与算法同名的成员函数.大多数情况下,应该使用这些成员函数,而不是相应的STL算法. 有两个理由: 成员函数往往速度快. 成员函数通常与容器结合地更紧密,这是算法所不能比的. ...

  5. 成员函数指针与高性能的C++委托

    成员函数指针与高性能的C++委托 http://www.cnblogs.com/jans2002/archive/2006/10/13/528160.html Member Function Poin ...

  6. 成员函数指针与高性能的C++委托(上篇)

    成员函数指针与高性能的C++委托(上篇) 撰文:Don Clugston 引子 标准C++中没有真正的面向对象的函数指针.这一点对C++来说是不幸的,因为面向对象的指针(也叫做"闭包(clo ...

  7. 成员函数指针与高性能的C++委托 (Member Function Pointers and the Fastest Possible C++ Delegates)...

    标准C++中没有真正的面向对象的函数指针.这一点对C++来说是不幸的,因为面向对象的指针(也叫做"闭包(closure)"或"委托(delegate)")在一些 ...

  8. C++ stl 通用算法和成员函数使用

    在stl中既有通用函数,又有相同成员函数主要表现在list中. 以remove为例 list<int> coll;// insert elements from 6 to 1 and 1 ...

  9. 求解多变量非线性全局最优解_约束条件下多变量非线性函数的区间算法.doc

    约束条件下多变量非线性函数的区间算法.doc 一种求解约束条件下多变量非线性函数所有全局最优解的区间算法李爽,许才军,王新洲(武汉大学测绘学院,湖北,武汉,430079)摘要研究和实践中经常会遇到附有 ...

最新文章

  1. golang 切片删除指定内容
  2. atitit.js javascript 调用c# java php后台语言api html5交互的原理与总结p97
  3. 干货!不得不知的UI界面中“行为召唤按钮”设计秘诀
  4. 深入解析Java字节码和字节码操作类库ASM源码解析
  5. 混合式安全灵活性可充分满足无边界企业的发展
  6. python爬取ajax动态内容肯德基门店,Python爬虫如何爬取KFC地址
  7. CocoaPods pod install/pod update更新慢的问题
  8. C++11 并发指南六(atomic 类型详解三 std::atomic (续))
  9. 微擎即用WIFI源码V2.1.7
  10. mysql完备_mysql简单完备脚本
  11. Live Meeting 音频视频使用端口设置
  12. laravel queue java_使用 Laravel Queue 不得不明白的知识
  13. js 正则 exec() 和 match() 数据抽取
  14. php laravel实战项目,Laravel框架应用:7个实战项目
  15. ppapi,npapi
  16. 荣耀play的android版本,荣耀Play3搭载了哪个版本系统 聪明的系统更懂你
  17. 禁用/开启 Windows系统3D加速
  18. 三星Q990B全景声回音壁评测
  19. 银行储蓄系统 类图 顺序图 E_R图 功能结构图 数据流图 系统流图 逻辑结构设计 关系模式 数据关系表
  20. 华为鸿蒙os家电,搭载华为鸿蒙OS的美的产品上市

热门文章

  1. 关于php抓取页面信息的简单代码
  2. delphi:多态置换原则
  3. 目前计算机无法显示的四叠字,四叠字列表(共19个),还能用的四叠字大全
  4. 第一代计算机到第四代计算机基本知识,[Ch01_计算机系统基本知识.ppt
  5. Metasploit设置LHOST参数技巧
  6. 网站截图工具EyeWitness
  7. PlayMaker布局技巧:预览GUI界面
  8. Xamarin中VS无法连接Mac系统的解决办法
  9. 计算机专业建设思路和措施,计算机网络专业教学改革与建设思路措施
  10. lzma打包exe_Web 项目打包EXE