技术开发 频道

泛型算法

【IT168技术文档】 一、只读算法

 1、使用两个迭代器和一个值调用 find 函数,检查两个迭代器实参标记范围内的每一个元素。只要找到与给定值相等的元素,find 就会返回指向该元素的迭代器。如果没有匹配的元素,find 就返回它的第二个迭代器实参,表示查找失败。于是,只要检查该函数的返回值是否与它的第二个实参相等,就可得知元素是否找到了。

 int search_value = 42;

 // call find to see if that value is present

 vector<int>::const_iterator result = find(vec.begin(), vec.end(), search_value);

 // report the result

 cout << "The value " << search_value

 << (result == vec.end()? " is not present" : " is present")

 << endl;

 2、许多算法只会读取其输入范围内的元素,而不会写这些元素。find 就是一个这样的算法。另一个简单的只读算法是 accumulate,accumulate 带有三个形参。头两个形参指定要累加的元素范围。第三个形参则是累加的初值。

 // sum the elements in vec starting the summation with the value 42

 int sum = accumulate(vec.begin(), vec.end(), 42);

 // concatenate elements from v and store in sum

 string sum = accumulate(v.begin(), v.end(), string(""));

 3、find_first_of 函数。这个算法带有两对迭代器参数来标记两段元素范围,在第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到元素,则返回第一个范围的 end 迭代器。假设 roster1 和 roster2 是两个存放名字的 list 对象,可使用 find_first_of 统计有多少个名字同时出现在这两个列表中:

 size_t cnt = 0;

 list<string>::iterator it = roster1.begin();

 // look in roster1 for any name also in roster2

 while   ((it = find_first_of(it, roster1.end(),roster2.begin(), roster2.end()))

 != roster1.end()) {

 ++cnt;

 // we got a match, increment it to look in the rest of roster1

 ++it;

 }

 cout << "Found " << cnt << " names on both rosters" << endl;

 二、写容器元素的算法

 1、写入到输入序列的算法本质上是安全的——只会写入与指定输入范围数量相同的元素,fill 带有一对迭代器形参,用于指定要写入的范围,而所写的值是它的第三个形参的副本。执行时,将该范围内的每个元素都设为给定的值。如果输入范围有效,则可安全写入。这个算法只会对输入范围内已存在的元素进行写入操作。

 // reset each element to 0

 fill(vec.begin(), vec.end(), 0);

 // set subsequence of the range to 10

 fill(vec.begin(), vec.begin() + vec.size()/2, 10);

 2、fill_n 函数带有的参数包括:一个迭代器、一个计数器以及一个值。该函数从迭代器指向的元素开始,将指定数量的元素设置为给定的值。fill_n 函数假定对指定数量的元素做写操作是安全的。初学者常犯的错误的是:在没有元素的空容器上调用 fill_n 函数(或者类似的写元素算法)。

vector<int> vec; // empty vector

 // disaster: attempts to write to 10 (nonexistent) elements in vec

 fill_n(vec.begin(), 10, 0);

  3、确保算法有足够的元素存储输出数据的一种方法是使用插入迭代器。插入迭代器是可以给基础容器添加元素的迭代器。通常,用迭代器给容器元素赋值时,被赋值的是迭代器所指向的元素。而使用插入迭代器赋值时,则会在容器中添加一个新元素,其值等于赋值运算的右操作数的值。

 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

 // appends 10 elements to vec

 fill_n (back_inserter(vec), 10, 0);

 4、向目标迭代器写入未知个数的元素。正如 fill_n 函数一样,目标迭代器指向存放输出数据的序列中第一个元素。这类算法中最简单的是 copy 函数。copy 带有三个迭代器参数:头两个指定输入范围,第三个则指向目标序列的一个元素。传递给 copy 的目标序列必须至少要与输入范围一样大。假设 ilst 是一个存放 int 型数据的 list 对象,可如下将它 copy 给一个 vector 对象:

 vector<int> ivec; // empty vector

 // copy elements from ilst into ivec

 copy (ilst.begin(), ilst.end(), back_inserter(ivec));

 5、有些算法提供所谓的“复制(copying)”版本。这些算法对输入序列的元素做出处理,但不修改原来的元素,而是创建一个新序列存储元素的处理结果。但不修改原来的元素,而是创建一个新序列存储元素的处理结果。replace 算法就是一个很好的例子。该算法对输入序列做读写操作,将序列中特定的值替换为新的值。该算法带有四个形参:一对指定输入范围的迭代器和两个值。每一个等于第一值的元素替换成第二个值。

 // replace any element with value of 0 by 42

 replace(ilst.begin(), ilst.end(), 0, 42);

 // create empty vector to hold the replacement

 vector<int> ivec;

 // use back_inserter to grow destination as needed

 //every element in ilst with the value 0 has the value 42 in ivec

 replace_copy (ilst.begin(), ilst.end(), back_inserter(ivec), 0, 42);

0
相关文章