Chapter 6
<algorithm>头
The header <algorithm> defines a collection offunctions especially designed to be used onranges of elements.
更多算法:http://www.cplusplus.com/reference/algorithm/
泛型算法std::copy()
泛型算法指不属于任何特定类别容器的算法。
前面第五章中
ret.insert (ret.end(), bottom.begin(), bottom.end() );
的替代版本是
copy ( bottom.begin(),bottom.end(), back_inserter( ret ) );
copy接受三个迭代器,并一次一个的将半开区间【first, second)中的元素赋值给third迭代器指向的元素,
然后++first, ++third;
std::back_inserter() //<iterator>头
是一种迭代器适配器函数,可以看作是一种特殊的输出迭代器,允许那些通常是覆盖元素的算法(如copy)变为自动在容器末尾插入新元素。
另外,back_inserter()要求参数是拥有push_back()成员的容器(如,vector,deque, list).
下面两种写法等价:
std::back_insert_iterator<vector<int> > it =std::back_inserter(vi);
*it = 88;
//等价于
vi.push_back(88 );
*third++ = *first++
*与++优先级相同,且都是右结合的,因此*first++ 就是 *(first++)
故上式等价于:{*third= *first; ++third; ++first;}
std::find_if
Find element in range
对函数的理解可参考这段代码:
1
2
3
4
5
6
7
8
9
|
template
<
class
InputIterator,
class
UnaryPredicate>
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while
(first!=last) {
if
(pred(*first))
return
first;
++first;
}
return
last;
}
|
相应的可以比较一下find函数的等价代码:
1
2
3
4
5
6
7
8
9
|
template
<
class
InputIterator,
class
T>
InputIterator find (InputIterator first, InputIterator last,
const
T& val)
{
while
(first!=last) {
if
(*first==val)
return
first;
++first;
}
return
last;
}
|
回文
1
2
3
4
|
bool
is_palindrome(
const
string& s)
{
return
std::equal(s.begin(), s.end(), s.rbegin());
}
|
std::equal()
测试两个范围内的元素是否相等,第三个参数是第二个序列的初始位置。
rbegin()
返回指向最后一个元素的反向迭代器。
std::transform()
等价代码:
1
2
3
4
5
6
7
8
9
10
|
template
<
class
InputIterator,
class
OutputIterator,
class
UnaryOperator>
OutputIterator transform (InputIterator first1, InputIterator last1,
OutputIterator result, UnaryOperator op)
{
while
(first1 != last1) {
*result = op(*first1);
// or: *result=binary_op(*first1,*first2++);
++result; ++first1;
}
return
result;
}
|
std::accumulate() //<numeric>头
Accumulate values in range
1
2
3
4
5
6
7
8
9
|
template
<
class
InputIterator,
class
T>
T accumulate (InputIterator first, InputIterator last, T init)
//注意第三个参数的类型决定返回值类型
{
while
(first!=last) {
init = init + *first;
++first;
}
return
init;
}
|
std::remove_copy()
把除去值为指定值的剩余所有元素复制到指定目的地。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
template
<
class
InputIterator,
class
OutputIterator,
class
T>
OutputIterator remove_copy (InputIterator first, InputIterator last,
OutputIterator result,
const
T& val)
{
while
(first!=last) {
if
(!(*first == val)) {
*result = *first;
++result;
}
++first;
}
return
result;
}
|
相应的有:remove_copy_if
std::remove_if() / std::remove()
把不满足remove谓词条件的移动(对那些满足remove条件的直接覆盖)到序列开头,返回新的end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
template
<
class
ForwardIterator,
class
UnaryPredicate>
ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred)
{
ForwardIterator result = first;
while
(first!=last) {
if
(!pred(*first)) {
*result = *first;
++result;
}
++first;
}
return
result;
//result是最后一个不被删除的元素后面的那个位置
}
|
remove()并不会改变容器的长度,删除元素可以使用erase+remove:
1
|
students.erase(remove_if ( students.begin(), students.end(), fgrade ), students.end() );
|
std::stable_partition() / std::partition()
对序列重新排列,谓词为true的排在前面,stable版本会保持原先的排列顺序。
返回true组的end(false组的第一个元素)。
以函数作为另一个函数的参数
1
2
3
4
5
6
7
8
9
10
11
|
int
foo(
int
x)
{
returnx*x;
}
void
use_foo(intx,
int
f(
int
))
//参数类似于函数声明
{
std::cout<< f(x) + x << std::endl;
}
……
use_foo(2, foo);
……
|
//来自chapter 10 的深入讲解
use_foo中的参数 int f( int ) 事实上会被编译器转化成一个指向这种类型函数的指针。因此这一参数也可以等价地写成:int ( *f )( int ) //意指 f 是指向具有一个int类型参数并返回int类型结果的函数的指针。
另一方面,use_foo( 2, foo ); 则会被编译器解释为 use_foo ( 2, &foo ); //我们也可以等价的这样写。
即传参时实际执行了 f = &foo; 的操作。//就像普通指针的用法一样。
也可以认为编译器会把 f = foo; 理解为 f = &foo; (编译器自动将函数名转化成指向函数的指针)
再另一方面,我们在use_foo函数中写 f(x),这实际上应该写成(*f)(x),//就像普通指针的用法一样。
二者都没问题是因为编译器自动认为二者是等价的。(编译器将对函数指针的调用自动地解释成对该指针指向函数的调用)
返回函数指针的函数
有两种写法:
1.
typedef int (*type_f)(int);
type_f get_foo_ptr();
2.
int ( *get_foo_ptr() ) (int);