在这里总结下可替代循环的区间成员函数和区间算法;java
相比单元素遍历操做,使用区间成员函数的优点在于:
1)更少的函数调用
2)更少的元素移动
3)更少的内存分配python
在区间成员函数不适用的状况下也应该使用区间算法,至少,相比手写循环而言,它更加简单,有效,而且不容易出错;c++
标准容器都支持区间构造函数:程序员
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
关联容器也支持区间插入,但因为其插入后的位置由其比较函数来决定,因此没有区间插入的位置这个参数;c++11
标准序列容器提供的erase:code
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:遍历,对每一个元素都执行一个动做;
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; }
对区间中每一个元素执行操做后,将修改后的值写入到新区间中;
能够认为这个是for_each()算法不修改原区间的版本;
仍是for_each中的例子:
int addfunction(int i ){ return i+5; } void output (int i) { // output function std::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的场景,均可以使用区间成员函数来替代(也建议这么作);
例:复制数组到vector:
int myints[]={10,20,30,40,50,60,70}; std::vector<int> myvector (7); std::copy ( myints, myints+7, myvector.begin() );
用一个元素来重复填充区间;
这个算法使用频率较低;
例:用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
遍历区间,进行值替换:
例:将如下区间中全部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()也很容易实现;
从区间中删除指定元素;
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-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 [订阅]
微博:新浪微博