C++ primer 十九 泛型算法replace/replace_copy/sort/unique

来源:互联网 发布:java强制类型转换性能 编辑:程序博客网 时间:2024/05/19 23:13
        replace算法读入一个序列,并将其中所有等于给定值的元素都改为另一个 值。此算法接受4个参数:前两个是迭代器,表示输入序列,后两个一个是要搜索的值, 另一个是新值。它将所有等亍第一个值的元素替换为第二个值:
//将所有值为0的元素改为42
replace (ilst.begin(), ilst.end(), 0, 42);
       此调用将序列中所有的0都荇换为42。如果我们希望保留原序列不变,可以调用 replaCe_C〇py。此算法接受额外第三个迭代器参数,指出调整后序列的保存位置:

//使用back_inserter按需要增长目标序列 

replace_copy(ilst.cbegin(), ilst.cend(), back_inserter(ivec), 0, 42);

此调用后,ilst并未改变,ivec包含ilst的一份拷W,不过原来在ilst中值为0的 元素在ivec中都变为42。

重排容器元素的算法

       某些算法会重排容器中元素的顺序,一个明显的例子是sort。调用sort会重排输入序列中的元素,使之有序,它是利用元素类型的<运算符来实现排序的。
       例如,假定我们想分析一系列儿童故事中所用的词汇。假定已有一个vector,保存 了多个故事的文本。我们希望化简这个vector,使得每个单词只出现一次,而不管单词 在任意给定文档中到底出现了多少次。
       为了便T说明问题,我们将使用下面简单的故事作为输入:

vector<string>vstr={"the","quick","red","fox","jumps","over","the","slow","red","turtle"};

消除重复单词

        为了消除重复单词,首先将vector排序,使得重复的单词都相邻出现。一旦vector 排序完毕,我们就可以使用另一个称为unique的标准库算法来重排vector,使得不重复的元素出现在vector的开始部分。由于算法不能执行容器的操作,我们将使用vector 的erase成员来完成真正的删除操作:

void elimdups(vector<string>&words)

{

//按字典序排序words,以便查找重复单词 

sort(words.begin(),words.end());

//unique重排输入范围,使得每个单词只出现一次 

//排列在范围的前部,返回指向不重复区域之后一个位置的迭代器 

vector<string>::iterator end_unique=unique(words.begin(),words.end());

//使用向量操作erase删除单词 

words.erase(end_unique,words.end());

for(const auto v:words)

cout<<v<<" ";

cout<<endl;

}

sort算法接受两个迭代器,表示要排序的元素范围。在此例中,我们排序整个vector。 完成sort后,words的顺序如下所不:

fox jumps over quick red red slow the the turtle

注意,单词red和the各出现了两次。

使用 unique 

        words排序完毕后,我们希望将每个单词都只保存一次。unique算法重排输入序列,将相邻的重复项“消除”,并返回一个指向不重复值范围末尾的迭代器。调用unique后,vector将变为:

fox jumps over quick red slow the turtle ??? ???

end_unique

(最后一个不重复完素之后的位置)

        words的大小并未改变,它仍有10个元素。但这些元素的顺序被改变了一相邻的 重复元素被“删除”了。我们将删除打引号是因为unique并不真的删除任何元素,它只是覆盖相邻的重复元素,使得不重复元素出现在序列开始部分。unique返回的迭代器指向最后一个不重复元素之后的位置。此位置之后的元素仍然存在,但我们不知道它们的值是什么。

使用容器操作删除元素

        为了真正地删除无用元素,我们必须使用容器操作,本例中使用erase。我们删除从end_unique开始直至words末尾的范围内的所有元素。 这个调用之后,words包含来自输入的8个不重复的单词。值得注意的是,即使words中没有重复单词,这样调用erase也是安全的。在此情况下,unique会返回words.end ()。因此,传递给erase的两个参数具有相同的值: words.end()。迭代器相等意味着传递给erase的元素范围为空。删除一个空范围没有什么不良后果,因此程序即使在输入中无重复元素的情况下也是正确的。

文件.cpp

#include<iostream>
#include <algorithm>    // std::replace 
#include<vector>
using namespace std;
void elimdups(vector<string>&words);
int main()
{
int a1[]={1,2,3,4,5,6,7,8,9};
int a2[sizeof(a1)/sizeof(*a1)];
auto ret=copy(begin(a1),end(a1),a2);

for(auto v:a2)
cout<<v<<" ";
cout<<endl;
cout<<"replace()改变容器中的值"<<endl;
vector<int>vec={1,2,3,4,5,6,7,8,9};
vector<int>vec2;
replace(vec.begin(),vec.end(),5,10);
//replace_copy(vec.cbegin(),vec.cend(),back_inserter(vec2),5,10);
for(auto v:vec)
cout<<v<<" ";
cout<<endl;
cout<<"replace_copy()复制替换"<<endl;
replace_copy(vec.cbegin(),vec.cend(),back_inserter(vec2),10,5);
for(auto v:vec2)
cout<<v<<" ";
cout<<endl;

cout<<"重排容器元素算法"<<endl;
vector<string>vstr={"the","quick","red","fox","jumps","over","the","slow","red","turtle"};

elimdups(vstr);

return 0;
}
void elimdups(vector<string>&words)
{
//按字典序排序words,以便查找重复单词 
sort(words.begin(),words.end());
//unique重排输入范围,使得每个单词只出现一次 
//排列在范围的前部,返回指向不重复区域之后一个位置的迭代器 
vector<string>::iterator end_unique=unique(words.begin(),words.end());
//使用向量操作erase删除单词 
words.erase(end_unique,words.end());

for(const auto v:words)
cout<<v<<" ";
cout<<endl;
}

运行结果:


0 0
原创粉丝点击