首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >STL中移动'移除'填充'替换算法

STL中移动'移除'填充'替换算法

作者头像
用户9831583
发布2022-06-16 15:28:18
发布2022-06-16 15:28:18
1.3K0
举报
文章被收录于专栏:码出名企路码出名企路
1.move()

将它的前两个输入迭代器参数指定的序列移到第三个参数定义的目的序列的开始位置,第三个参数必须是输出迭代器。

返回值:返回的迭代器指向最后一个被移动到目的序列的元素的下一个位置。

缺陷:这是一个移动操作,因此无法保证在进行这个操作之后,输入序列仍然保持不变;源元素仍然会存在,但它们的值可能不再相同了,因此在移动之后,就不应该再使用它们。

如果源序列可以被替换或破坏,就可以选择使用move() 算法。如果不想扰乱源序列,可以使用 copy() 算法。

2.swap_ranges()

交换两个序列。

参数定义:前两个参数分别是第一个序列的开始和结束迭代器,第三个参数是第二个序列的开始迭代器。显然,这两个序列的长度必须相同。

返回值:返回指向第二个序列的最后一个被交换元素的下一个位置的迭代器。

3.remove()
  • remove() 可以从它的前两个正向迭代器参数指定的序列中移除和第三个参数相等的对象。基本上每个元素都是通过用它后面的元素覆盖它来实现移除的。它会返回一个指向新的最后一个元素之后的位置的迭代器。
  • remove_copy() 可以将前两个正向迭代器参数指定的序列中的元素复制到第三个参数指定的目的序列中,并忽略和第 4 个参数相等的元素。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。
  • remove_if() 可以从前两个正向迭代器指定的序列中移除能够使作为第三个参数的谓词返回 true 的元素。
  • remove_copy_if() 可以将前两个正向迭代器参数指定的序列中,能够使作为第 4 个参数的谓词返回 true 的元素,复制到第三个参数指定的目的序列中。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。

1-2-3代码实例:

代码语言:javascript
复制
   #include <iostream>                                    
    #include <vector>                                      
    #include <algorithm>                                    
    #include <string>                                        
    #include <iterator>
    #include <deque>
    #include <utility>
    #include <list>
    #include <set>
 
using namespace std;

    int main()
    {  
        //move
        std::vector<int> srce {1, 2, 3, 4};
        deque<int>   dest{5, 6, 7, 8};
        std::move(std::begin(srce), std::end(srce), std::back_inserter(dest));
        std::copy(std::begin (dest), std::end(dest), std::ostream_iterator<int> {std::cout, " "});
        std::cout << std::endl;

        //将前 6 个元素向右移动两个位置
        std::vector<int> data {1, 2, 3, 4, 5, 6, 7, 8};
        std::move(std::begin(data) + 2, std::end(data), std::begin(data));
        data.erase(std::end(data) - 2, std::end(data)); // Erase moved elements
        std::copy(std::begin (data), std::end(data), std::ostream_iterator<int> {std::cout, " "});
        std::cout << std::endl;


        //swap_ranges
        //交换元素
        using Name = pair<string, string>;
        std::vector<Name> people{Name{"Al", "Bedo" }, Name{ "Ann", "Ounce"}, Name{"Jo","King"}};
        std::list<Name> folks{Name{"Stan", "Down"}, Name{"Dan","Druff"},Name{"Bea", "Gone"}};
        
        //swap_ranges() 算法被用来交换 people 的前两个元素和 folks 的后两个元素
        std::swap_ranges(std::begin(people), std::begin(people) + 2, ++std::begin(folks));

        //用 for_each() 算法将 lambda 表达式运用到容器的每个元素上
        std::for_each(std::begin(people), std::end(people),
                [](const Name& name) {std::cout << '"' << name.first << " " << name.second << "\" ";});
        std::cout << std::endl;
        std::for_each (std::begin (folks) , std::end (folks) ,
                    [] (const Name& name){std::cout << '"' << name.first << " " << name.second << "\" "; });
        std::cout << std::endl;


        // remove()
        //原来的改变了
        std::deque<double> samples {1.5, 2.6, 0.0, 3.1, 0.0, 0.0, 4.1, 0.0, 6.7, 0.0};
        //可以消除杂乱分布的 0
        //remove() 返回的迭代器指向通过这个操作得到的新序列的尾部,所以可以用它作为被删除序列的开始迭代器
        samples.erase(std::remove(std::begin(samples), std::end(samples), 0.0), std::end(samples));
        std::copy(std::begin(samples),std::end(samples), std::ostream_iterator <double> {std::cout," "});
        std::cout << std::endl;

        //remove_copy()
        //如果想保留原始序列,并生成一个移除选定元素之后的副本
        //samples 容器中的非零元素会被复制到 edited_samples 容器中,这个容器只包含从 sample 中复制的元素
          std::deque<double> samples1{1.5, 2.6, 0.0, 3.1, 0.0, 0.0, 4.1, 0.0, 6.7, 0.0};
         std::vector<double> edited_samples;
         std::remove_copy(std::begin(samples1), std::end(samples1), std::back_inserter(edited_samples), 0.0);
         std::copy(std::begin(samples1),std::end(samples1), std::ostream_iterator <double> {std::cout," "});
        std::cout << std::endl;


        //remove_if()
        //它能够从序列中移除和给定值匹配的元素。谓词会决定一个元素是否被移除;它接受序列中的一个元素为参数,并返回一个布尔值
        std::set<Name> blacklist{Name {"Al", "Bedo"}, Name {"Ann", "Ounce"}, Name {"Jo","King"}};
        std::deque<Name> candidates{Name{"Stan", "Down"}, Name {"Al", "Bedo"}, Name {"Dan", "Druff"},
                                                Name {"Di", "Gress"}, Name {"Ann", "Ounce"}, Name {"Bea", "Gone"}};
        //当参数在容器中存在时,set 容器的成员函数 count() 会返回 1
        //谓词返回的值会被隐式转换为布尔值,因此对于每一个出现在 blacklist 中的候选人,
        //谓词都会返回 true,然后会将它们从 candidates 中移除
        candidates.erase(std::remove_if(std::begin(candidates), std::end(candidates),
                        [&blacklist](const Name& name) { return blacklist.count(name); }), std::end(candidates));
       std::for_each(std::begin(candidates), std::end(candidates),
                    [] (const Name& name){std::cout << '"' << name.first << " " << name.second << "\" ";});
        std::cout << std::endl;  

        //remove_copy_if()
        //保留了候选人的原始序列,生成一个副本
        std::deque<Name> validated;
        std::remove_copy_if(std::begin(candidates) , std::end(candidates), std::back inserter(validated),
                            [&blacklist] (const Name& name) { return blacklist.count(name); });
    }

结果显示:

4.fill()

提供了一种为元素序列填入给定值的简单方式。

fill() 会填充整个序列;fill_n() 则以给定的迭代器为起始位置,为指定个数的元素设置值

代码实例:

代码语言:javascript
复制
   #include <iostream>                                    
    #include <vector>                                      
    #include <algorithm>                                    
    #include <string>                                        
    #include <iterator>
    #include <deque>
    #include <utility>
    #include <list>
    #include <set>
 
using namespace std;

int main()
{
    //fill
    //fill 的前两个参数是定义序列的正向迭代器,第三个参数是赋给每个元素的值
    std::vector<string> data {12};
    std::fill(std::begin (data), std::end (data), "none");
    std::copy(std::begin (data), std::end(data), std::ostream_iterator<string> {std::cout, " "});
    std::cout << std::endl;

    //这个序列并不一定要代表容器的全部元素
    //具有 13 个元素的 value 容器
    std::deque<int> values(13);
    int n{2};  
    const int step{7};
    const size_t count{3};  
    auto iter = std::begin(values);
    while(true)
    {
        auto to_end = std::distance(iter, std::end(values));
        //fill() 算法会将 values 赋值给 count 个元素
        //以 iter 作为容器的开始迭代器,如果还有足够的元素剩下,每次遍历中,它会被加上 count,因此它会指向下个序列的第一个元素
        if (to_end < count)
        {  
            std::fill(iter, iter + to_end, n);
            break;
        }
        else
        {
            std::fill(iter, std:: end(values), n);
        }
        iter = std::next(iter, count);
        n += step;
    }
    std::copy(std::begin (values), std::end(values), std::ostream_iterator<int> {std::cout, " "});
    std::cout << std::endl;
}

结果显示:

5.transform()

将函数应用到序列的元素上,并将这个函数返回的值保存到另一个序列中。

返回值:返回的迭代器指向输出序列所保存的最后一个元素的下一个位置。

参数定义:前两个参数是定义输入序列的输入迭代器,第 3 个参数是目的位置的第一个元素的输出迭代器,第 4 个参数是一个二元函数。这个函数必须接受来自输入序列的一个元素为参数,并且必须返回一个可以保存在输出序列中的值。

6.replace()

用新的值来替换和给定值相匹配的元素。

  • replace()前两个参数是被处理序列的正向迭代器,第 3 个参数是被替换的值,第 4 个参数是新的值。
  • replace_if() 会将使谓词返回 true 的元素替换为新的值。它的第 3 个参数是一个谓词,第 4 个参数是新的值。参数的类型一般是元素类型的 const 引用;const 不是强制性的,但谓词不应该改变元素。
  • replace_copy() 和 replace() 做的事是一样的,但它的结果会被保存到另一个序列中,而不会改变原始序列。它的前两个参数是输入序列的正向迭代器,第 3 个参数是输入序列的开始迭代器,最后两个参数分别是要被替换的值和替换值。
  • replace_copy_if()和 replace_if() 算法是相同的,但它的结果会被保存到另一个序列中。它的前两个参数是输入序列的迭代器,第 3 个参数是输出序列的开始迭代器,最后两个参数分别是谓词和替换值。

5-6代码实例:

代码语言:javascript
复制
   #include <iostream>                                    
    #include <vector>                                      
    #include <algorithm>                                    
    #include <string>                                        
    #include <iterator>
    #include <deque>
    #include <utility>
    #include <list>
    #include <set>
 
using namespace std;

int main()
{
    std::vector<double> deg_C {21.0, 30.5, 0.0, 3.2, 100.0};
    std::vector<double> deg_F(deg_C.size());
    std::transform(std::begin(deg_C), std::end(deg_C), std::begin(deg_F),
                                [](double temp){ return 32.0 + 9.0*temp/5.0; });
     std::copy(std::begin(deg_F), std::end(deg_F),std::ostream_iterator<double> {std::cout," "});
     cout<<endl;

    using Point = std::pair<double, double>;
    std::vector<Point> hexagon {{1,2}, {2,1}, {3,1}, {4,2}, {3,3}, {2,3}, {1,2}};
    std::vector<double> segments;
    //transform() 的第一个输入序列包含六边形中从第一个到倒数第二个 Point 对象。第二个输入序列是从第二个 Point 对象开始的
    //因此这个二元函数调用的连续参数为点 1 和 2、点 2 和 3、点 3 和 4,依此类推,直到输入序列的最后两个点 6 和 7。
    std::transform(std::begin(hexagon),std::end(hexagon) -1, std::begin(hexagon) +1,std::back_inserter(segments),[](const Point p1, const Point p2){
                    return std::sqrt((p1.first-p2.first)*(p1.first-p2.first) +(p1.second - p2.second)*(p1.second - p2.second)); });
    //输出线段的长度和这个六边形的周长
    std::cout << "Segment lengths: "<<endl;
    std::copy(std::begin(segments), std::end(segments),std::ostream_iterator<double> {std::cout," "});
    std::cout << std::endl;
    std::cout << "Hexagon perimeter: "<< std::accumulate(std::begin(segments), std::end(segments), 0.0) << std::endl;
 

    //replace
    //data 容器中和 10 匹配的全部元素都会被 99 替代
    std::deque<int> data {10, -5, 12, -6, 10, 8, -7, 10, 11};
    std::replace(std::begin(data), std::end(data), 10, 99);
    std::copy(std::begin(data), std::end(data),std::ostream_iterator<double> {std::cout," "});
     cout<<endl;


     //replace_if
     //这个谓词会为任何是空格字符的元素返回 true,因此这里的空格都会被下划线代替。
    string password { "This is a good choice !"};
    std::replace_if(std::begin(password), std::end(password),[](char ch){return std::isspace(ch);}, '_');
    std::copy(std::begin(password), std::end(password),std::ostream_iterator<double> {std::cout," "});
     cout<<endl;
  

    //replace_copy
    //最后两个参数分别是要被替换的值和替换值
    std::vector<string> words{ "one","none", "two", "three", "none", "four"};
    std::vector<string> new_words;
    std::replace_copy(std::begin(words), std::end(words), std::back_inserter(new_words),
                string{"none"}, string{"0"});
    std::copy(std::begin(new_words), std::end(new_words),std::ostream_iterator<string> {std::cout," "});
     cout<<endl;

     //replace_copy_if()
    std::deque<int> data1{10, -5, 12, -6, 10, 8, -7, 10,11};
     std::vector<int> data_copy;
    std::replace_copy_if(std::begin(data1), std::end(data1),std::back_inserter(data_copy),
                [](int value) {return value == 10;}, 99);
    std::copy(std::begin(data_copy), std::end(data_copy),std::ostream_iterator<int> {std::cout," "});
     cout<<endl;
    
}

结果显示:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码出名企路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.move()
  • 2.swap_ranges()
  • 3.remove()
  • 4.fill()
  • 5.transform()
  • 6.replace()
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档