标签:
#include<algorithm>
标准库还定义了一组泛华的算术算法,命名习惯和泛型算法相同,使用这些算法必须:
#include<numeric>
? #include<numeric>
int sum = accumulate(vec.begin(), vec.end(), 42);
用于指定累加起始值的第三个实参是必要的,因为 accumulate 对将要累加的元素类型一无所知,因此,除此之外,没有别的办法创建合适的起始值或者关联的类型。容器内的元素类型必须与第三个实参的类型匹配,或者可转换为第三个实参的类型。
使用 accumulate 把 string 型的 vector 容器中的元素连接起来:
string sum = accumulate(v.begin(), v.end(), string(""));
如果传递一个字符串字面值,将会导致编译时错误。因为此时,累加和的类型将是 const char*,而 string 的加法操作符所使用的操作数则分别是 string 和 const char* 类型,加法的结果将产生一个 string 对象,而不是 const char* 指针。
? fill(vec.begin(), vec.end(), 0)
fill_n(vec.begin(), 10, 0)
对指定数目的元素做写入运算,或者写到目标迭代器的算法,都不检查目标的大小是否足以存储要写入的元素。所以一定要注意!
? back_inserter
确保算法有足够的元素存储输出数据的一种方法是使用插入迭代器。插入迭代器是可以给基础容器添加元素的迭代器。通常,用迭代器给容器元素赋值时,被赋值的是迭代器所指向的元素。而使用插入迭代器赋值时,则会在容器中添加一个新元素,其值等于赋值运算的右操作数的值。
back_inserter 函数是迭代器适配器。与容器适配器一样,迭代器适配器使用一个对象作为实参,并生成一个适应其实参行为的新对象。在本例中,传递给 back_inserter 的实参是一个容器的引用。back_inserter 生成一个绑定在该容器上的插入迭代器。在试图通过这个迭代器给元素赋值时,赋值运算将调用 push_back 在容器中添加一个具有指定值的元素。
vector<int> vec; // empty vector
// ok: back_inserter creates an insert iterator that adds elements to vec
fill_n (back_inserter(vec), 10, 0); // appends 10 elements to vec
? replace(vec.begin(), vec.end(), 0, 42)
如果不想改变原来的序列,则用replace_copy
replace_copy(vec.begin(), vec.end(), back_inserter(ilst), 0, 42)
则把vec的内容替换并复制到了ilst中。
? 例子:假设我们要分析一组儿童故事中所使用的单词。例如,可能想知道它们使用了多少个由六个或以上字母组成的单词。每个单词只统计一次,不考虑它出现的次数,也不考虑它是否在多个故事中出现。要求以长度的大小输出这些单词,对于同样长的单词,则以字典顺序输出。
为了解此问题,要做下面几项操作:
1. 去掉所有重复的单词。
2. 按单词的长度排序。
3. 统计长度等于或超过 6 个字符的单词个数。
假设存到了vector<string> words中
v sort(words.begin(), words.end());
vector<string>::iterator end_unique =unique(words.begin(), words.end());
words.erase(end_unique, words.end());
unique 的使用
单词按次序排列后,现在的问题是:让故事中所用到的每个单词都只保留一个副本。unique 算法很适合用于解决这个问题,它带有两个指定元素范围的迭代器参数。该算法删除相邻的重复元素,然后重新排列输入范围内的元素,并且返回一个迭代器,表示无重复的值范围的结束。调用 unique“删除”了相邻的重复值。给“删除”加上引号是因为 unique 实际上并没有删除任何元素,而是将无重复的元素复制到序列的前端,从而覆盖相邻的重复元素。unique 返回的迭代器指向超出无重复的元素范围末端的下一位置。
fox jumps over quick red red slow the the turtle
变为
v 下一个子问题统计长度不小于 6 的单词个数。为了解决这个问题,需要用到另外两个泛型算法:stable_sort 和 count_if。使用这些算法,还需要一个配套的实用函数,称为谓词。谓词是做某些检测的函数,返回用于条件判断的类型,指出条件是否成立。
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
bool GT6(const string &s)
{
return s.size() >= 6;
}
除了 sort 之外,标准库还定义了 stable_sort 算法,stable_sort 保留相等元素的原始相对位置。sort 和 stable_sort 都是重载函数。其中一个版本使用元素类型提供的小于(<)操作符实现比较。在查找重复元素之前,我们就是用这个 sort 版本对元素排序。第二个重载版本带有第三个形参:比较元素所使用的谓词函数的名字。这个谓词函数必须接受两个实参,实参的类型必须与元素类型相同,并返回一个可用作条件检测的值。
stable_sort(words.begin(), words.end(), isShorter);
v vector<string>::size_type wc = count_if(words.begin(), words.end(), GT6);
整个代码如下:
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
string make_plural(int wc, const string &word, const string &ending){
return (wc==1)?word:word+ending;
}
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
bool GT6(const string &s)
{
return s.size() >= 6;
}
int main()
{
vector<string> words;
string next_word;
while (cin >> next_word) {
words.push_back(next_word);
}
sort (words.begin(), words.end());
vector<string>::iterator end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
stable_sort(words.begin(), words.end(), isShorter);
vector<string>::size_type wc = count_if (words.begin(), words.end(), GT6);
cout << wc << " " << make_plural(wc, "word", "s")<< " 6 characters or longer" << endl;
vector<string>::iterator iter=words.begin();
for(; iter!=words.end(); ++iter){
cout<<*iter<<endl;
}
return 0;
}
? 算法命名规范
查找某个值的算法通常提供第二个版本,用于查找使谓词函数返回非零值的元素。对于这种算法,第二个版本的函数名字以 _if 后缀标识。类似地,很多算法提供所谓的复制版本,将(修改过的)元素写到输出序列,而不是写回输入范围。这种版本的名字以 _copy 结束。
? 算法从不改变序列的大小
算法从不直接改变它所操纵的序列的大小。(如果算法的实参是插入迭代器,则该迭代器会添加新元素,但算法并不直接这么做。)算法可以从一个位置将元素复制到另一个位置,但不直接添加或删除元素。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/qhairen/article/details/47253681