C++进阶篇二:C++标准模版库之算法
2017-04-13 00:00
253 查看
摘要: C++的标准模版库(Standard template library, STL)强大之处,除了它有多种多样的数据结构(容器)和迭代可供选择,处理这些容器和迭代的算法也是值得探讨的话题之一。本文作为楼主C++ STL的第二篇学习笔记,比较完整简明地整理介绍了常用的STL算法及其使用方式。
此外,当对容器作出修改时(比如对vector应用clear或erase方法),在应用方法前的迭代可能会失效。插入(insert操作)对于各容器的作用如下:
vector:若vector的空间被重新分配,所有之前的迭代均无效。其他情况下,从插入点到end位置的迭代无效。
deque:全部迭代失效。
list, forward_list以及顺序关联型容器:全部迭代有效。
非顺序关联型容器:若容器空间被重新分配则所有迭代失效。
当从容器中擦除元素时(erase操作),被擦除部分的迭代失效。另需注意,
对vector来说,从被擦除位置到end位置的元素全部无效。
对deque来说,如果队列中间部分元素被擦除,则所有迭代无效。
在其中可以查到各种算法函数(点击Algorithms library)。例如,查询transform函数可获得以下两条C++11有关信息:
此处,InputIt就表示输入迭代,OutputIt就表示输出迭代,UnaryOperation表示传入参数为一个的单元操作函数,BinaryOperation表示传入参数为二元的函数。此外,还有ForwardIt表示向前迭代,RandomIt 表示随机存取以及 Compare表示传入函数对象等。
以transform函数为例,第一个重载函数即表示了传入参数前两个为输入迭代,第三个参数为输出迭代以及最后一个参数为单元操作函数指针;而第二个重载函数的不同之处在于最后一个传入参数可以是二元操作函数。
any_of(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内的存在元素,能使bool_func函数为true。返回值为bool。
accumulate(iter.cbegin(), iter.cend(), initVal, [how_to_accu]):头文件<numeric>,第三个参数为积分的初始值。第四个参数为可选参数,为一个指定了计算积分的方式的函数头。该指定积分方式的函数必须以当前和和下一项为传入值,返回值为当前和与下一项值进行运算之后的结果。
copy(iter_begin(), iter_end(), ostream):将迭代范围内的容器拷贝到输出中,本函数要求前两个传入参数至少为输入迭代。它有一个类似方法copy_backward(iter.cbegin(), iter.cend(), output.end()),常用于将元素倒序放入。其它的拷贝函数还有copy_if和copy_n。但是copy_backward前两个参数要求的最低迭代权限为双向迭代。
count(iter.cbegin(), iter.cend(), ele):统计ele元素迭代范围内出现的次数。
count_if(iter.cbegin(), iter.cend(), bool_func):在迭代范围内统计使得bool_func为true的元素个数.
equal(iter1.cbegin(), iter1.cend(), iter2.cbegin(), [predicate]):比较两个数据结构是否内容完全相同,返回值为bool。
find(iter.cbegin(), iter.cend(), ele):在迭代范围内寻找ele元素,并返回其迭代位置。若未找到,返回迭代终止位置。本函数前两个参数支持的最低权限为输入迭代。
find_if(iter.cbegin(), iter.cend(), bool_func):在迭代范围内寻找第一个使得bool_func为true的元素,并返回其迭代位置。若未找到,返回迭代终止位置。
find_if_not(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内存在元素,能使bool_func函数为false,返回值为bool。
for_each(iter.cbegin(), iter.cend(), func):对迭代范围内的每一个元素按照func函数进行操作。
includes(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), [predicate]):检测第二个集合是否包含在第一个集合中,返回值为bool。
lexicographical_compare(begin(c1), end(c1), begin(c2), end(c2)):比较内置char数组,返回值为bool。
minmax_element(iter.cbegin(), iter.cend(), [predicate]):找到数据结构中的最小最大元素对应的迭代,以对值形式返回。其对应的两个只返回最小最大元素迭代的函数分别为:min_element(iter.cbegin(), iter.cend(), [predicate])和max_element(iter.cbegin(), iter.cend(), [predicate])。
mismatch(iter1.cbegin(), iter1.cend(), iter2.cbegin(), [predicate]):比较两个容器中的不同部分,返回值为一个对值。
merge(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), output.begin(), [predicate]):将两个已经排序完毕的数据结构归并到result数据结构中。
none_of(iter.begin(), iter.end(), bool_func):判断是否迭代范围内的所有元素都能使bool_func函数为false,返回值为bool。
remove_copy(iter1.cbegin(), iter1.cend(), output.cbegin(), ele):将数据结构1中迭代范围内的元素复制到输出迭代中,并移除所有ele元素。返回值为被复制到输出迭代的最后一个元素所对应的迭代。
remove_copy_if(iter1.cbegin(), iter1.cend(), output.begin(), bool_func):可参照remove和remove_copy之间的关系从remove_if函数推知该函数功能,返回值为最后一个被复制元素的迭代。
replace_copy(iter1.cbegin(), iter1.cend(), output.begin(), ele1, ele2):复制数据结构迭代范围内的数据,粘帖到数据结构2迭代起始位置并将结构1中的ele1元素全部用ele2元素替代,返回值同考remove_copy。
replace_copy_if(iter1.cbegin(), iter1.cend(), iter2.start(), bool_func, ele):功能可参照remove_copy_if得知,返回值和权限同remove_copy_if函数。
set_difference(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1 - U2的集合操作。
set_intersection(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1交U2的集合操作。
set_symmetric_difference(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):选出集合1和2分别独有的元素,存入difference数据结构中。
set_union(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1并U2的集合操作。
transform(iter1.cbegin(), iter1.cend(), [iter2.begin()], output.begin(), opfunc):将迭代范围内的每一个元素(数据结构2存在时为每一对元素)按照opfunc指定的方法处理,输出到output数据结构中。若可选参数被传入时,opfunc必须为一个二元操作函数,否则为一元操作函数。
unique_copy(iter.begin(), iter.end(), output, [predicate]):将迭代范围内的元素去重吼存入output数据结构中。
注:
未特殊说明时,iter指输入迭代,output指输出迭代。
此处集合操作未特殊声明,应理解为对数据结构的操作,而非数学定义的集合,因为操作中允许重复元素。
eqaul_range(iter.cbegin(), iter.cend(), ele, [predicate]):查找最早和最晚适合插入ele元素的插入点位置对应的迭代,返回值为表示这两个位置的对值,类型均为向前迭代。
fill(iter.begin(), iter.end(), data):用数据data将指定数据结构迭代范围内的位置填满。若未填满这个数据结构,其余部分保持原值。
fill_n(iter.begin(), n, data):从起始迭代位置将data向数据结构中填入n次。若填充过程中遇到数据结构结束,则填充到结束位置为止。
generate(iter.begin(), iter.end(), data):用数据data将指定数据结构迭代范围填满。若未填满这个数据结构,其余部分保持原值。
generate_n(iter.begin(), iter.end(), data):从起始迭代位置将data向数据结构中填入n次。若填充过程中遇到数据结构结束,则填充到结束位置为止。
iter_swap(iter.begin(), iter.end()):通过使用迭代器的方式交换这两个迭代分别对应的元素。
lower_bound(iter.cbegin(), iter.cend(), ele, [predicate]):查找最早适合插入ele元素的插入点位置对应的迭代,返回值为表示该位置的向前迭代。
min_element(iter.begin(), iter.end(), [predicate]):在迭代范围内找出最小元素首次出现所在的迭代位置,返回值为该位置的向前迭代。
max_element(iter.begin(), iter.end(), [predicate]):在迭代范围内找出最大元素首次出现所在的迭代位置,返回值同上。
minmax_element(iter.begin(), iter.end(), [predicate]):在迭代范围内分别找出最小最大元素首次出现所在的迭代位置,返回值为对值,第一个值表示最小元素,第二个则为最大元素。
remove(iter.begin(), iter.end(), ele):移去数据结构中迭代范围内出现的所有ele元素,返回值为最后一个未被移除的元素的迭代位置。
remove_if(iter.begin(), iter.end(), boo_func):在迭代范围内移去所有符合满足使得用户定义的bool函数为true的元素,返回值为最后一个未被移除的元素的迭代位置。
replace(iter.begin(), iter.end(), ele1, ele2):将数据结构迭代范围内的所有ele1元素替换为ele2元素。
replace_if(iter.begin(), iter.end(), bool_func, ele):在迭代范围内将符合满足用户定义的bool函数为true的元素全部替换为元素ele。
swap_ranges(iter.begin(), iter.end(), iter.start()):将迭代范围内的元素与从iter_start()位置开始的元素进行交换。两个范围不能重叠,但可以是同一个数据结构内的范围,也可是不同数据结构的范围。
unique(iter_begin(), iter_end()):返回迭代范围内指向数据结构最末单个元素的迭代。
upper_bound(iter.cbegin(), iter.cend(), ele, [predicate]):查找最晚适合插入ele元素的插入点位置对应的迭代,返回值为表示该位置的向前迭代。
reverse(iter.begin(), iter.end()):倒置迭代范围内的所有元素。
reverse_copy(iter.begin(), iter.end(), output):将数据结构中的元素倒置后置入输出容器中。
push_heap(iter.begin(), iter.end(), [predicate]):将数据结构end位置元素加入由其它元素构成的堆中。(假设其他元素已构成堆)
pop_heap(iter.begin(), iter.end(), [predicate]):将堆顶元素推出堆,放在end位置,并将剩余元素进行调堆。
random_shuffle(iter.begin(), iter.end(), [rand_generator]):打乱迭代范围内元素,其中rand_generator为可选函数。
sort(iter.begin(), iter.end(), [predicate]):将迭代范围内的数据元素进行排序。
sort_heap(iter.begin(), iter.end(), [predicate]):根据已有堆进行堆排序。
参数中若有c开头的迭代(cbegin或cend)表示此处可以使用常量迭代(作用类似于常量指针),没有则必须使用变量迭代。
迭代范围值从迭代起始位置到迭代终止位置。
未经特殊说明,本文所指的迭代起始位置包括起始的那个元素的迭代,而迭代终止位置则不包括。
凡是返回元素所在位置迭代的,若未查找到该元素或数据结构中所有元素都已遍历,则返回end位置的迭代,没有实际意义。
对值(pair object)是指由两个分别指向迭代起始和迭代终止位置组成的一对指针,一般形式为```
auto p = pair_obj;
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator> // ostream_iterator
using namespace std;
char nextLetter(); // prototype of generator function
int main()
{
array< char, 10 > chars;
ostream_iterator< char > output(cout, " ");
fill(chars.begin() + 1, chars.end(), nextLetter()); // fill chars with 5s
} // end main
// generator function returns next letter (starts with A)
char nextLetter()
{
static char letter = 'A';
return letter++;
} // end function nextLetter
template<class ForwardIterator, class Generator>
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator> // ostream_iterator
using namespace std;
int main()
{
const size_t SIZE = 10;
array< int, SIZE > a1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
array< int, SIZE > a2( a1 ); // initializes a2 with copy of a1
array< int, SIZE > a3 = { 1, 2, 3, 4, 1000, 6, 7, 8, 9, 10 };
ostream_iterator< int > output( cout, " " );
// compare a1 and a2 for equality
bool result = equal( a1.cbegin(), a1.cend(), a2.cbegin() );
cout << "a1 " << ( result ? "is" : "is not" )
<< " equal to a2." << endl;
// compare a1 and a3 for equality
result = equal( a1.cbegin(), a1.cend(), a3.cbegin() );
cout << "a1 " << ( result ? "is" : "is not" ) << " equal to a3. " << endl;
// check for mismatch between a1 and a3
auto location = mismatch( a1.cbegin(), a1.cend(), a3.cbegin() );
cout << "\nThere is a mismatch between a1 and a3 at location "
<< ( location.first - a1.begin() ) << "\nwhere a1 contains "
<< *location.first << " and a3 contains " << *location.second
<< "\n" << endl;
char c1[ SIZE ] = "HELLO";
char c2[ SIZE ] = "BYE BYE";
// perform lexicographical comparison of c1 and c2
result = lexicographical_compare(
begin( c1 ), end( c1 ), begin( c2 ), end( c2 ) );
cout << c1 << ( result ? " is less than " :
" is greater than or equal to " ) << c2 << endl;
} // end main
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator> // ostream_iterator
using namespace std;
bool greater9( int ); // prototype
int main()
{
const size_t SIZE = 10;
array< int, SIZE > init = { 10, 2, 10, 4, 16, 6, 14, 8, 12, 10 };
ostream_iterator< int > output( cout, " " );
array< int, SIZE > a1( init ); // initialize with copy of init
cout << "a1 before removing all 10s: ";
copy( a1.cbegin(), a1.cend(), output );
cout << endl;
// remove all 10s from a1
auto newLastElement = remove( a1.begin(), a1.end(), 10 );
cout << "a1 after removing all 10s: ";
copy( a1.begin(), newLastElement, output );
cout << endl;
array< int, SIZE > a2( init ); // initialize with copy of init
array< int, SIZE > c = { 0 }; // initialize to 0s
// copy from a2 to c, removing 10s in the process
remove_copy( a2.cbegin(), a2.cend(), c.begin(), 10 );
cout << "\nc after removing all 10s from a2: ";
copy( c.cbegin(), c.cend(), output );
cout << endl;
array< int, SIZE > a3( init ); // initialize with copy of init
// remove elements greater than 9 from a3
newLastElement = remove_if( a3.begin(), a3.end(), greater9 );
cout << "a3 after removing all elements greater than 9: ";
copy( a3.begin(), newLastElement, output );
cout << endl;
array< int, SIZE > a4( init ); // initialize with copy of init
array< int, SIZE > c2 = { 0 }; // initialize to 0s
// copy elements from a4 to c2, removing elements greater
// than 9 in the process, greater9 is only function header.
remove_copy_if( a4.begin(), a4.end(), c2.begin(), greater9 );
cout << "c2 after removing all elements"
<< "greater than 9 from a4: ";
copy( c2.cbegin(), c2.cend(), output );
cout << endl;
} // end main
// determine whether argument is greater than 9
bool greater9( int x )
{
return x > 9;
} // end function greater9
// Fig. 16.5: fig16_05.cpp
// Mathematical algorithms of the Standard Library.
#include <iostream>
#include <algorithm> // algorithm definitions
#include <numeric> // accumulate is defined here
#include <array>
#include <iterator>
#include <random>
#include <ctime>
using namespace std;
bool greater9( int ); // predicate function prototype
void outputSquare( int ); // output square of a value
int sumMultiply( int, int ); // calculate cube of a value
int myrandom(int i) {
srand(time(0));
return std::rand() % i;
}
bool reverseCompare(int num1, int num2){
return num1 > num2;
}
int howToAccumulate(int sum, int item){
return sum + (item << 1);
}
int calculateCube(int val){ return val * val * val;}
int main()
{
const int SIZE = 10;
array< int, SIZE > a1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
ostream_iterator< int > output( cout, " " );
cout << "a1 before random_shuffle: ";
copy( a1.cbegin(), a1.cend(), output );
random_shuffle(a1.begin(), a1.end(), myrandom);
cout << "\na1 after random_shuffle: ";
copy( a1.cbegin(), a1.cend(), output );
array< int, SIZE > a2 = { 100, 2, 8, 1, 50, 3, 8, 8, 9, 10 };
cout << "\n\na2 contains: ";
copy( a2.cbegin(), a2.cend(), output );
// count number of elements in a2 with value 8
int result = count( a2.cbegin(), a2.cend(), 8 );
cout << "\nNumber of elements matching 8: " << result;
// count number of elements in a2 that are greater than 9
result = count_if( a2.cbegin(), a2.cend(), greater9 );
cout << "\nNumber of elements greater than 9: " << result;
// locate minimum element in a2
cout << "\n\nMinimum element in a2 is: "
<< *( min_element( a2.cbegin(), a2.cend(), reverseCompare ) );
// locate maximum element in a2
cout << "\nMaximum element in a2 is: "
<< *( max_element( a2.cbegin(), a2.cend() ) );
// locate minimum and maximum elements in a2
auto minAndMax = minmax_element( a2.cbegin(), a2.cend() );
cout << "\nThe minimum and maximum elements in a2 are "
<< *minAndMax.first << " and " << *minAndMax.second
<< ", respectively";
// calculate sum of elements in a1
cout << "\n\nThe twice of the total of the elements in a1 is: "
<< accumulate( a1.cbegin(), a1.cend(), 0, howToAccumulate );
// output square of every element in a1
cout << "\n\nThe square of every integer in a1 is:\n";
for_each( a1.cbegin(), a1.cend(), outputSquare );
array< int, SIZE > multiplieSum; // instantiate multiplieSum
array<int, SIZE> cubes;
// calculate cube of each element in a1; place results in cubes
transform( a1.cbegin(), a1.cend(), a2.cbegin(), multiplieSum.begin(), sumMultiply );
cout << "\n\nThe sum of muliply of one element in a1 and another in a2 is:\n";
copy( multiplieSum.cbegin(), multiplieSum.cend(), output );
cout << endl;
transform( a1.cbegin(), a1.cend(), cubes.begin(), calculateCube );
cout << "\n\nThe cubes of all elements in a1 is:\n";
copy( cubes.cbegin(), cubes.cend(), output );
cout << endl;
} // end main
// determine whether argument is greater than 9
bool greater9( int value )
{
return value > 9;
} // end function greater9
// output square of argument
void outputSquare( int value )
{
cout << value * value << ' ';
} // end function outputSquare
// return cube of argument
int sumMultiply( int val1, int val2 )
{
return val1 * val2;
} // end function calculateCube
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator>
using namespace std;
bool greater10( int value ); // predicate function prototype
bool intCompare(int num1, int num2){
return num1 > num2;
}
int main()
{
const size_t SIZE = 10;
array< int, SIZE > a = { 10, 2, 17, 5, 16, 8, 13, 11, 20, 7 };
ostream_iterator< int > output( cout, " " );
cout << "array a contains: ";
copy( a.cbegin(), a.cend(), output ); // display output vector
// locate first occurrence of 16 in a
auto location = find( a.cbegin(), a.cend(), 16 );
if ( location != a.cend() ) // found 16
cout << "\n\nFound 16 at location " << ( location - a.cbegin() );
else // 16 not found
cout << "\n\n16 not found";
// locate first occurrence of 100 in a
location = find( a.cbegin(), a.cend(), 100 );
if ( location != a.cend() ) // found 100
cout << "\nFound 100 at location " << ( location - a.cbegin() );
else // 100 not found
cout << "\n100 not found";
// locate first occurrence of value greater than 10 in a
location = find_if( a.cbegin(), a.cend(), greater10 );
if ( location != a.cend() ) // found value greater than 10
cout << "\n\nThe first value greater than 10 is " << *location
<< "\nfound at location " << ( location - a.cbegin() );
else // value greater than 10 not found
cout << "\n\nNo values greater than 10 were found";
// sort elements of a
//sort( a.begin(), a.end() );
//Sort in reverse order:
sort( a.begin(), a.end(), intCompare );
cout << "\n\narray a after sort: ";
copy( a.cbegin(), a.cend(), output );
// use binary_search to locate 13 in a
if ( binary_search( a.cbegin(), a.cend(), 13, intCompare ) )
cout << "\n\n13 was found in a, location: " <<
(find( a.cbegin(), a.cend(), 13 ) - a.cbegin()) << endl;
else
cout << "\n\n13 was not found in a";
// use binary_search to locate 100 in a
if ( binary_search( a.cbegin(), a.cend(), 100 ) )
cout << "\n100 was found in a";
else
cout << "\n100 was not found in a";
// determine whether all of the elements of a are greater than 10
if ( all_of( a.cbegin(), a.cend(), greater10 ) )
cout << "\n\nAll the elements in a are greater than 10";
else
cout << "\n\nSome elements in a are not greater than 10";
// determine whether any of the elements of a are greater than 10
if ( any_of( a.cbegin(), a.cend(), greater10 ) )
cout << "\n\nSome of the elements in a are greater than 10";
else
cout << "\n\nNone of the elements in a are greater than 10";
// determine whether none of the elements of a are greater than 10
if ( none_of( a.cbegin(), a.cend(), greater10 ) )
cout << "\n\nNone of the elements in a are greater than 10";
else
cout << "\n\nSome of the elements in a are greater than 10";
// locate first occurrence of value that's not greater than 10 in a
location = find_if_not( a.cbegin(), a.cend(), greater10 );
if ( location != a.cend() ) // found a value less than or eqaul to 10
cout << "\n\nThe first value not greater than 10 is " << *location
<< "\nfound at location " << ( location - a.cbegin() );
else // no values less than or equal to 10 were found
cout << "\n\nOnly values greater than 10 were found";
cout << endl;
} // end main
// determine whether argument is greater than 10
bool greater10( int value )
{
return value > 10;
} // end function greater10
// Fig. 16.7: fig16_07.cpp
// Algorithms iter_swap, swap and swap_ranges.
#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
using namespace std;
// sort using a custom function object
struct {
bool operator()(int a, int b) {
return a > b;
}
} customLess;
int main()
{
const size_t SIZE = 10;
array< int, SIZE > a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
array< int, SIZE > b = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
array<int, 5> c = {15, 13, 11, 9, 7};
ostream_iterator< int > output( cout, " " );
// swap elements in first five elements of array a with
// elements in last five elements of array a
swap_ranges( a.begin(), a.begin() + 5, b.begin() + 5 );
cout << "\nArray a, b after the process: " << endl;
copy( a.cbegin(), a.cend(), output );
cout << endl;
copy( b.cbegin(), b.cend(), output );
cout << endl;
sort(b.begin(), b.end(), std::greater<int>());
copy( b.cbegin(), b.cend(), output );
cout << endl;
vector<int> result;
merge(b.cbegin(), b.cend(), c.cbegin(), c.cend(), back_inserter(result), std::greater<int>());
/Below is also available, but is in C-Style:
merge(b.cbegin(), b.cend(), c.cbegin(), c.cend(), back_inserter(result), customLess);/
cout << "Merge result: ";
copy( result.cbegin(), result.cend(), output );
cout << endl;
auto endLocation = unique(result.begin(), result.end());
for(auto p = endLocation; p <= result.end(); p++)
result.pop_back();
cout << "After unique and reverse, result contains: ";
reverse(result.begin(), result.end());
copy(result.begin(), result.end(), output);
cout << endl;
} // end main
#include <iostream>
#include <array>
#include <algorithm> // algorithm definitions
#include <iterator> // ostream_iterator
using namespace std;
int main()
{
const size_t SIZE1 = 10, SIZE2 = 5, SIZE3 = 20;
array< int, SIZE1 > a1 = { 1, 2, 2, 4, 5, 6, 7, 8, 9, 10 };
array< int, SIZE2 > a2 = { 4, 5, 6, 7, 8 };
array< int, SIZE2 > a3 = { 4, 5, 6, 11, 15 };
ostream_iterator< int > output( cout, " " );
// determine whether a2 is completely contained in a1
if ( includes( a1.cbegin(), a1.cend(), a2.cbegin(), a2.cend() ) )
cout << "a1 includes a2";
else
cout << "a1 does not include a2";
cout << endl;
// determine whether a3 is completely contained in a1
if ( includes( a1.cbegin(), a1.cend(), a3.cbegin(), a3.cend() ) )
cout << "a1 includes a3";
else
cout << "a1 does not include a3";
cout << "\n" << endl;
array< int, SIZE1 > difference;
// determine elements of a1 not in a2
auto result1 = set_difference( a1.cbegin(), a1.cend(),
a2.cbegin(), a2.cend(), difference.begin() );
cout << "set_difference of a1 and a2 is: ";
copy( difference.begin(), result1, output );
cout << endl;
array< int, SIZE1 > intersection;
// determine elements in both a1 and a2
auto result2 = set_intersection( a1.cbegin(), a1.cend(),
a2.cbegin(), a2.cend(), intersection.begin() );
cout << "set_intersection of a1 and a2 is: ";
copy( intersection.begin(), result2, output );
cout << endl;
array< int, SIZE1 + SIZE2 > symmetric_difference;
// determine elements of a1 that are not in a2 and
// elements of a2 that are not in a1
auto result3 = set_symmetric_difference( a1.cbegin(), a1.cend(),
a3.cbegin(), a3.cend(), symmetric_difference.begin() );
cout << "set_symmetric_difference of a1 and a3 is: ";
copy( symmetric_difference.begin(), result3, output );
cout << endl;
array< int, SIZE3 > unionSet;
// determine elements that are in either or both sets
auto result4 = set_union( a1.cbegin(), a1.cend(),
a3.cbegin(), a3.cend(), unionSet.begin() );
cout << "set_union of a1 and a3 is: ";
copy( unionSet.begin(), result4, output );
cout << endl;
} // end main
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
const size_t SIZE = 10;
array< int, SIZE > init = { 3, 100, 52, 77, 22, 31, 1, 98, 13, 40 };
array< int, SIZE > a( init ); // copy of init
ostream_iterator< int > output( cout, " " );
make_heap( a.begin(), a.end() ); // create heap from array a
cout << "Array a after make_heap: ";
copy( a.cbegin(), a.cend(), output );
cout << endl;
sort_heap( a.begin(), a.end() ); // sort elements with sort_heap
cout << "Array a after sort_heap: ";
copy( a.cbegin(), a.cend(), output );
cout << endl;
// perform the heapsort with push_heap and pop_heap
cout << "\nArray init contains: ";
copy( init.cbegin(), init.cend(), output ); // display array init
cout << endl;
vector< int > v;
// place elements of array init into v and
// maintain elements of v in heap
for ( size_t i = 0; i < init.size(); ++i )
{
v.push_back( init[ i ] );
push_heap( v.begin(), v.end() );
cout << "\nv after push_heap(init[" << i << "]): ";
copy( v.cbegin(), v.cend(), output );
} // end for
cout << endl;
// remove elements from heap in sorted order
for ( size_t j = 0; j < v.size(); ++j )
{
cout << "\nv after " << v[ 0 ] << " popped from heap\n";
pop_heap( v.begin(), v.end() - j );
copy( v.cbegin(), v.cend(), output );
} // end for
cout << endl;
} // end main
写在<algorithm>头文件之前
在C++STL的头文件<algorithm>中,各式算法函数往往会对支持该算法的最低迭代级别作出要求。任何算法作用的容器或迭代,只有支持的权限等于或高于算法要求的最低迭代级别,才能适用该算法。(关于迭代级别,可参考楼主文章:《一篇文章看懂C++ 标准模板库容器和迭代》,URL:https://my.oschina.net/SamYjy/blog/855953 )比如某个算法需要至少向前迭代级别支持,则该算法可以应用于所有迭代级别高于或等于向前迭代的容器。因此,STL算法函数的学习中,就可以按照算法所支持的迭代级别对算法进行分类。此外,当对容器作出修改时(比如对vector应用clear或erase方法),在应用方法前的迭代可能会失效。插入(insert操作)对于各容器的作用如下:
vector:若vector的空间被重新分配,所有之前的迭代均无效。其他情况下,从插入点到end位置的迭代无效。
deque:全部迭代失效。
list, forward_list以及顺序关联型容器:全部迭代有效。
非顺序关联型容器:若容器空间被重新分配则所有迭代失效。
当从容器中擦除元素时(erase操作),被擦除部分的迭代失效。另需注意,
对vector来说,从被擦除位置到end位置的元素全部无效。
对deque来说,如果队列中间部分元素被擦除,则所有迭代无效。
C++ STL算法查看方式(以transform函数为例):
cppreference 为C++ DOC的一个使用说明网页。网址:http://en.cppreference.com/w/在其中可以查到各种算法函数(点击Algorithms library)。例如,查询transform函数可获得以下两条C++11有关信息:
template< class InputIt, class OutputIt, class UnaryOperation > OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op ); template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation > OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op );
此处,InputIt就表示输入迭代,OutputIt就表示输出迭代,UnaryOperation表示传入参数为一个的单元操作函数,BinaryOperation表示传入参数为二元的函数。此外,还有ForwardIt表示向前迭代,RandomIt 表示随机存取以及 Compare表示传入函数对象等。
以transform函数为例,第一个重载函数即表示了传入参数前两个为输入迭代,第三个参数为输出迭代以及最后一个参数为单元操作函数指针;而第二个重载函数的不同之处在于最后一个传入参数可以是二元操作函数。
C++ STL常用算法一览:
C++标准模版库中的常用算法非常之多,有90多种。限于篇幅,本文仅仅列举一些《C++11程序设计》中介绍的常用算法,并且将他们按照对应传入参数迭代级别(事实上即为可应用范围从广到窄)的方式进行分类,在文末附上一些算法的使用示例,以便于快速查询算法及其用法。最低权限为输入输出迭代的函数
all_of(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内的所有元素都能使bool_func函数为true。返回值为bool。any_of(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内的存在元素,能使bool_func函数为true。返回值为bool。
accumulate(iter.cbegin(), iter.cend(), initVal, [how_to_accu]):头文件<numeric>,第三个参数为积分的初始值。第四个参数为可选参数,为一个指定了计算积分的方式的函数头。该指定积分方式的函数必须以当前和和下一项为传入值,返回值为当前和与下一项值进行运算之后的结果。
copy(iter_begin(), iter_end(), ostream):将迭代范围内的容器拷贝到输出中,本函数要求前两个传入参数至少为输入迭代。它有一个类似方法copy_backward(iter.cbegin(), iter.cend(), output.end()),常用于将元素倒序放入。其它的拷贝函数还有copy_if和copy_n。但是copy_backward前两个参数要求的最低迭代权限为双向迭代。
count(iter.cbegin(), iter.cend(), ele):统计ele元素迭代范围内出现的次数。
count_if(iter.cbegin(), iter.cend(), bool_func):在迭代范围内统计使得bool_func为true的元素个数.
equal(iter1.cbegin(), iter1.cend(), iter2.cbegin(), [predicate]):比较两个数据结构是否内容完全相同,返回值为bool。
find(iter.cbegin(), iter.cend(), ele):在迭代范围内寻找ele元素,并返回其迭代位置。若未找到,返回迭代终止位置。本函数前两个参数支持的最低权限为输入迭代。
find_if(iter.cbegin(), iter.cend(), bool_func):在迭代范围内寻找第一个使得bool_func为true的元素,并返回其迭代位置。若未找到,返回迭代终止位置。
find_if_not(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内存在元素,能使bool_func函数为false,返回值为bool。
for_each(iter.cbegin(), iter.cend(), func):对迭代范围内的每一个元素按照func函数进行操作。
includes(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), [predicate]):检测第二个集合是否包含在第一个集合中,返回值为bool。
lexicographical_compare(begin(c1), end(c1), begin(c2), end(c2)):比较内置char数组,返回值为bool。
minmax_element(iter.cbegin(), iter.cend(), [predicate]):找到数据结构中的最小最大元素对应的迭代,以对值形式返回。其对应的两个只返回最小最大元素迭代的函数分别为:min_element(iter.cbegin(), iter.cend(), [predicate])和max_element(iter.cbegin(), iter.cend(), [predicate])。
mismatch(iter1.cbegin(), iter1.cend(), iter2.cbegin(), [predicate]):比较两个容器中的不同部分,返回值为一个对值。
merge(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), output.begin(), [predicate]):将两个已经排序完毕的数据结构归并到result数据结构中。
none_of(iter.begin(), iter.end(), bool_func):判断是否迭代范围内的所有元素都能使bool_func函数为false,返回值为bool。
remove_copy(iter1.cbegin(), iter1.cend(), output.cbegin(), ele):将数据结构1中迭代范围内的元素复制到输出迭代中,并移除所有ele元素。返回值为被复制到输出迭代的最后一个元素所对应的迭代。
remove_copy_if(iter1.cbegin(), iter1.cend(), output.begin(), bool_func):可参照remove和remove_copy之间的关系从remove_if函数推知该函数功能,返回值为最后一个被复制元素的迭代。
replace_copy(iter1.cbegin(), iter1.cend(), output.begin(), ele1, ele2):复制数据结构迭代范围内的数据,粘帖到数据结构2迭代起始位置并将结构1中的ele1元素全部用ele2元素替代,返回值同考remove_copy。
replace_copy_if(iter1.cbegin(), iter1.cend(), iter2.start(), bool_func, ele):功能可参照remove_copy_if得知,返回值和权限同remove_copy_if函数。
set_difference(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1 - U2的集合操作。
set_intersection(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1交U2的集合操作。
set_symmetric_difference(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):选出集合1和2分别独有的元素,存入difference数据结构中。
set_union(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1并U2的集合操作。
transform(iter1.cbegin(), iter1.cend(), [iter2.begin()], output.begin(), opfunc):将迭代范围内的每一个元素(数据结构2存在时为每一对元素)按照opfunc指定的方法处理,输出到output数据结构中。若可选参数被传入时,opfunc必须为一个二元操作函数,否则为一元操作函数。
unique_copy(iter.begin(), iter.end(), output, [predicate]):将迭代范围内的元素去重吼存入output数据结构中。
注:
未特殊说明时,iter指输入迭代,output指输出迭代。
此处集合操作未特殊声明,应理解为对数据结构的操作,而非数学定义的集合,因为操作中允许重复元素。
最低权限为向前迭代的函数
binary_search(iter.cbegin(), iter.cend(), ele, [predicate]):通过二分查找的方式在迭代范围内(要求已排序)判断迭代范围内是否存在该元素,返回值为bool。eqaul_range(iter.cbegin(), iter.cend(), ele, [predicate]):查找最早和最晚适合插入ele元素的插入点位置对应的迭代,返回值为表示这两个位置的对值,类型均为向前迭代。
fill(iter.begin(), iter.end(), data):用数据data将指定数据结构迭代范围内的位置填满。若未填满这个数据结构,其余部分保持原值。
fill_n(iter.begin(), n, data):从起始迭代位置将data向数据结构中填入n次。若填充过程中遇到数据结构结束,则填充到结束位置为止。
generate(iter.begin(), iter.end(), data):用数据data将指定数据结构迭代范围填满。若未填满这个数据结构,其余部分保持原值。
generate_n(iter.begin(), iter.end(), data):从起始迭代位置将data向数据结构中填入n次。若填充过程中遇到数据结构结束,则填充到结束位置为止。
iter_swap(iter.begin(), iter.end()):通过使用迭代器的方式交换这两个迭代分别对应的元素。
lower_bound(iter.cbegin(), iter.cend(), ele, [predicate]):查找最早适合插入ele元素的插入点位置对应的迭代,返回值为表示该位置的向前迭代。
min_element(iter.begin(), iter.end(), [predicate]):在迭代范围内找出最小元素首次出现所在的迭代位置,返回值为该位置的向前迭代。
max_element(iter.begin(), iter.end(), [predicate]):在迭代范围内找出最大元素首次出现所在的迭代位置,返回值同上。
minmax_element(iter.begin(), iter.end(), [predicate]):在迭代范围内分别找出最小最大元素首次出现所在的迭代位置,返回值为对值,第一个值表示最小元素,第二个则为最大元素。
remove(iter.begin(), iter.end(), ele):移去数据结构中迭代范围内出现的所有ele元素,返回值为最后一个未被移除的元素的迭代位置。
remove_if(iter.begin(), iter.end(), boo_func):在迭代范围内移去所有符合满足使得用户定义的bool函数为true的元素,返回值为最后一个未被移除的元素的迭代位置。
replace(iter.begin(), iter.end(), ele1, ele2):将数据结构迭代范围内的所有ele1元素替换为ele2元素。
replace_if(iter.begin(), iter.end(), bool_func, ele):在迭代范围内将符合满足用户定义的bool函数为true的元素全部替换为元素ele。
swap_ranges(iter.begin(), iter.end(), iter.start()):将迭代范围内的元素与从iter_start()位置开始的元素进行交换。两个范围不能重叠,但可以是同一个数据结构内的范围,也可是不同数据结构的范围。
unique(iter_begin(), iter_end()):返回迭代范围内指向数据结构最末单个元素的迭代。
upper_bound(iter.cbegin(), iter.cend(), ele, [predicate]):查找最晚适合插入ele元素的插入点位置对应的迭代,返回值为表示该位置的向前迭代。
最低权限为双向迭代的函数
inplace_merge(iter.begin(), iter.checkpoint(), iter.end()):将数据结构内部迭代范围内的元素进行归并。其中,要求begin至checkpoint(不包括)以及从checkpoint(包括)至终止位置的元素都分别相应已经排序。reverse(iter.begin(), iter.end()):倒置迭代范围内的所有元素。
reverse_copy(iter.begin(), iter.end(), output):将数据结构中的元素倒置后置入输出容器中。
最低权限为随机存取的函数
make_heap(iter.begin(), iter.end(), [predicate]):用数据结构迭代范围内的元素建堆。push_heap(iter.begin(), iter.end(), [predicate]):将数据结构end位置元素加入由其它元素构成的堆中。(假设其他元素已构成堆)
pop_heap(iter.begin(), iter.end(), [predicate]):将堆顶元素推出堆,放在end位置,并将剩余元素进行调堆。
random_shuffle(iter.begin(), iter.end(), [rand_generator]):打乱迭代范围内元素,其中rand_generator为可选函数。
sort(iter.begin(), iter.end(), [predicate]):将迭代范围内的数据元素进行排序。
sort_heap(iter.begin(), iter.end(), [predicate]):根据已有堆进行堆排序。
STL函数若干注意:
fill 和generate是有区别的,简而言之,fill只是从头到尾填充同一个浅拷贝的元素,而generate则是生成深拷贝的元素(从样例程序和参考资料 中都可以看出来)参数中若有c开头的迭代(cbegin或cend)表示此处可以使用常量迭代(作用类似于常量指针),没有则必须使用变量迭代。
迭代范围值从迭代起始位置到迭代终止位置。
未经特殊说明,本文所指的迭代起始位置包括起始的那个元素的迭代,而迭代终止位置则不包括。
凡是返回元素所在位置迭代的,若未查找到该元素或数据结构中所有元素都已遍历,则返回end位置的迭代,没有实际意义。
对值(pair object)是指由两个分别指向迭代起始和迭代终止位置组成的一对指针,一般形式为```
auto p = pair_obj;
1. 文中由中括号包括的为可选参数,[predicate]是C++函数对象,可以是函数指针、函数对象和lambda表达式,关于此参数的使用,可以详见楼主博客《小论C++函数对象在STL算法函数中的应用》,URL:https://my.oschina.net/SamYjy/blog/878125。 ### 仅针对排序后的数据结构进行操作的算法: binary_search, lower_bound, upper_bound, equal_range, includes, set_difference, set_intersection, set_symmetric_difference, set_union。(可以简要概括为二分查找、范围算法和集合操作) 例1:fill和generate函数使用示例
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator> // ostream_iterator
using namespace std;
char nextLetter(); // prototype of generator function
int main()
{
array< char, 10 > chars;
ostream_iterator< char > output(cout, " ");
fill(chars.begin() + 1, chars.end(), nextLetter()); // fill chars with 5s
cout << "chars after filling with 5s:\n"; copy(chars.cbegin(), chars.cend(), output); // fill first five elements of chars with As fill_n(chars.begin() + 8, 5, 'X'); cout << "\nchars after filling five elements with As:\n"; copy(chars.cbegin(), chars.cend(), output); // generate values for all elements of chars with nextLetter generate(chars.begin(), chars.end(), nextLetter); cout << "\nchars after generating letters A-J:\n"; copy(chars.cbegin(), chars.cend(), output); // generate values for first five elements of chars with nextLetter generate_n(chars.begin(), 5, nextLetter); cout << "\nchars after generating K-O for the" << " first five elements:\n"; copy(chars.cbegin(), chars.cend(), output); cout << endl;
} // end main
// generator function returns next letter (starts with A)
char nextLetter()
{
static char letter = 'A';
return letter++;
} // end function nextLetter
![输入图片说明](https://static.oschina.net/uploads/img/201703/19152113_EaEm.png "在这里输入图片标题") 备注:因为fill只是填入对于同一个元素复制第一次的拷贝,所以会发现全部插入的是暂存字符串A。而因为generate使用的是深拷贝,所以输出的字符串从B开始了。 此外,由于generate函数在C++标准文档中的定义是:
template<class ForwardIterator, class Generator>
其中Generator事实上可以为函数指针、函数对象或者lambda表达式。 例2:比较函数equal, mismatch以及lexicographical_compare示例:
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator> // ostream_iterator
using namespace std;
int main()
{
const size_t SIZE = 10;
array< int, SIZE > a1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
array< int, SIZE > a2( a1 ); // initializes a2 with copy of a1
array< int, SIZE > a3 = { 1, 2, 3, 4, 1000, 6, 7, 8, 9, 10 };
ostream_iterator< int > output( cout, " " );
// compare a1 and a2 for equality
bool result = equal( a1.cbegin(), a1.cend(), a2.cbegin() );
cout << "a1 " << ( result ? "is" : "is not" )
<< " equal to a2." << endl;
// compare a1 and a3 for equality
result = equal( a1.cbegin(), a1.cend(), a3.cbegin() );
cout << "a1 " << ( result ? "is" : "is not" ) << " equal to a3. " << endl;
// check for mismatch between a1 and a3
auto location = mismatch( a1.cbegin(), a1.cend(), a3.cbegin() );
cout << "\nThere is a mismatch between a1 and a3 at location "
<< ( location.first - a1.begin() ) << "\nwhere a1 contains "
<< *location.first << " and a3 contains " << *location.second
<< "\n" << endl;
char c1[ SIZE ] = "HELLO";
char c2[ SIZE ] = "BYE BYE";
// perform lexicographical comparison of c1 and c2
result = lexicographical_compare(
begin( c1 ), end( c1 ), begin( c2 ), end( c2 ) );
cout << c1 << ( result ? " is less than " :
" is greater than or equal to " ) << c2 << endl;
} // end main
![输入图片说明](https://static.oschina.net/uploads/img/201704/13210309_1Iy5.png "在这里输入图片标题") 例3:移除类算法remove, remove_if, remove_copy以及remove_copy_if示例:
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator> // ostream_iterator
using namespace std;
bool greater9( int ); // prototype
int main()
{
const size_t SIZE = 10;
array< int, SIZE > init = { 10, 2, 10, 4, 16, 6, 14, 8, 12, 10 };
ostream_iterator< int > output( cout, " " );
array< int, SIZE > a1( init ); // initialize with copy of init
cout << "a1 before removing all 10s: ";
copy( a1.cbegin(), a1.cend(), output );
cout << endl;
// remove all 10s from a1
auto newLastElement = remove( a1.begin(), a1.end(), 10 );
cout << "a1 after removing all 10s: ";
copy( a1.begin(), newLastElement, output );
cout << endl;
array< int, SIZE > a2( init ); // initialize with copy of init
array< int, SIZE > c = { 0 }; // initialize to 0s
// copy from a2 to c, removing 10s in the process
remove_copy( a2.cbegin(), a2.cend(), c.begin(), 10 );
cout << "\nc after removing all 10s from a2: ";
copy( c.cbegin(), c.cend(), output );
cout << endl;
array< int, SIZE > a3( init ); // initialize with copy of init
// remove elements greater than 9 from a3
newLastElement = remove_if( a3.begin(), a3.end(), greater9 );
cout << "a3 after removing all elements greater than 9: ";
copy( a3.begin(), newLastElement, output );
cout << endl;
array< int, SIZE > a4( init ); // initialize with copy of init
array< int, SIZE > c2 = { 0 }; // initialize to 0s
// copy elements from a4 to c2, removing elements greater
// than 9 in the process, greater9 is only function header.
remove_copy_if( a4.begin(), a4.end(), c2.begin(), greater9 );
cout << "c2 after removing all elements"
<< "greater than 9 from a4: ";
copy( c2.cbegin(), c2.cend(), output );
cout << endl;
} // end main
// determine whether argument is greater than 9
bool greater9( int x )
{
return x > 9;
} // end function greater9
![输入图片说明](https://static.oschina.net/uploads/img/201704/13210826_qKo3.png "在这里输入图片标题") 例4:常用数值操作random_shuffle, count, count_if, min_element, max_element, minmax_element, accumulate, for_each以及transform操作示例:
// Fig. 16.5: fig16_05.cpp
// Mathematical algorithms of the Standard Library.
#include <iostream>
#include <algorithm> // algorithm definitions
#include <numeric> // accumulate is defined here
#include <array>
#include <iterator>
#include <random>
#include <ctime>
using namespace std;
bool greater9( int ); // predicate function prototype
void outputSquare( int ); // output square of a value
int sumMultiply( int, int ); // calculate cube of a value
int myrandom(int i) {
srand(time(0));
return std::rand() % i;
}
bool reverseCompare(int num1, int num2){
return num1 > num2;
}
int howToAccumulate(int sum, int item){
return sum + (item << 1);
}
int calculateCube(int val){ return val * val * val;}
int main()
{
const int SIZE = 10;
array< int, SIZE > a1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
ostream_iterator< int > output( cout, " " );
cout << "a1 before random_shuffle: ";
copy( a1.cbegin(), a1.cend(), output );
random_shuffle(a1.begin(), a1.end(), myrandom);
cout << "\na1 after random_shuffle: ";
copy( a1.cbegin(), a1.cend(), output );
array< int, SIZE > a2 = { 100, 2, 8, 1, 50, 3, 8, 8, 9, 10 };
cout << "\n\na2 contains: ";
copy( a2.cbegin(), a2.cend(), output );
// count number of elements in a2 with value 8
int result = count( a2.cbegin(), a2.cend(), 8 );
cout << "\nNumber of elements matching 8: " << result;
// count number of elements in a2 that are greater than 9
result = count_if( a2.cbegin(), a2.cend(), greater9 );
cout << "\nNumber of elements greater than 9: " << result;
// locate minimum element in a2
cout << "\n\nMinimum element in a2 is: "
<< *( min_element( a2.cbegin(), a2.cend(), reverseCompare ) );
// locate maximum element in a2
cout << "\nMaximum element in a2 is: "
<< *( max_element( a2.cbegin(), a2.cend() ) );
// locate minimum and maximum elements in a2
auto minAndMax = minmax_element( a2.cbegin(), a2.cend() );
cout << "\nThe minimum and maximum elements in a2 are "
<< *minAndMax.first << " and " << *minAndMax.second
<< ", respectively";
// calculate sum of elements in a1
cout << "\n\nThe twice of the total of the elements in a1 is: "
<< accumulate( a1.cbegin(), a1.cend(), 0, howToAccumulate );
// output square of every element in a1
cout << "\n\nThe square of every integer in a1 is:\n";
for_each( a1.cbegin(), a1.cend(), outputSquare );
array< int, SIZE > multiplieSum; // instantiate multiplieSum
array<int, SIZE> cubes;
// calculate cube of each element in a1; place results in cubes
transform( a1.cbegin(), a1.cend(), a2.cbegin(), multiplieSum.begin(), sumMultiply );
cout << "\n\nThe sum of muliply of one element in a1 and another in a2 is:\n";
copy( multiplieSum.cbegin(), multiplieSum.cend(), output );
cout << endl;
transform( a1.cbegin(), a1.cend(), cubes.begin(), calculateCube );
cout << "\n\nThe cubes of all elements in a1 is:\n";
copy( cubes.cbegin(), cubes.cend(), output );
cout << endl;
} // end main
// determine whether argument is greater than 9
bool greater9( int value )
{
return value > 9;
} // end function greater9
// output square of argument
void outputSquare( int value )
{
cout << value * value << ' ';
} // end function outputSquare
// return cube of argument
int sumMultiply( int val1, int val2 )
{
return val1 * val2;
} // end function calculateCube
![输入图片说明](https://static.oschina.net/uploads/img/201704/01155242_YL02.png "在这里输入图片标题") 例5:常用查找、排序操作find, find_if, sort, binary_search, all_of, any_of, none_of和find_if_not操作使用示例:
#include <iostream>
#include <algorithm> // algorithm definitions
#include <array> // array class-template definition
#include <iterator>
using namespace std;
bool greater10( int value ); // predicate function prototype
bool intCompare(int num1, int num2){
return num1 > num2;
}
int main()
{
const size_t SIZE = 10;
array< int, SIZE > a = { 10, 2, 17, 5, 16, 8, 13, 11, 20, 7 };
ostream_iterator< int > output( cout, " " );
cout << "array a contains: ";
copy( a.cbegin(), a.cend(), output ); // display output vector
// locate first occurrence of 16 in a
auto location = find( a.cbegin(), a.cend(), 16 );
if ( location != a.cend() ) // found 16
cout << "\n\nFound 16 at location " << ( location - a.cbegin() );
else // 16 not found
cout << "\n\n16 not found";
// locate first occurrence of 100 in a
location = find( a.cbegin(), a.cend(), 100 );
if ( location != a.cend() ) // found 100
cout << "\nFound 100 at location " << ( location - a.cbegin() );
else // 100 not found
cout << "\n100 not found";
// locate first occurrence of value greater than 10 in a
location = find_if( a.cbegin(), a.cend(), greater10 );
if ( location != a.cend() ) // found value greater than 10
cout << "\n\nThe first value greater than 10 is " << *location
<< "\nfound at location " << ( location - a.cbegin() );
else // value greater than 10 not found
cout << "\n\nNo values greater than 10 were found";
// sort elements of a
//sort( a.begin(), a.end() );
//Sort in reverse order:
sort( a.begin(), a.end(), intCompare );
cout << "\n\narray a after sort: ";
copy( a.cbegin(), a.cend(), output );
// use binary_search to locate 13 in a
if ( binary_search( a.cbegin(), a.cend(), 13, intCompare ) )
cout << "\n\n13 was found in a, location: " <<
(find( a.cbegin(), a.cend(), 13 ) - a.cbegin()) << endl;
else
cout << "\n\n13 was not found in a";
// use binary_search to locate 100 in a
if ( binary_search( a.cbegin(), a.cend(), 100 ) )
cout << "\n100 was found in a";
else
cout << "\n100 was not found in a";
// determine whether all of the elements of a are greater than 10
if ( all_of( a.cbegin(), a.cend(), greater10 ) )
cout << "\n\nAll the elements in a are greater than 10";
else
cout << "\n\nSome elements in a are not greater than 10";
// determine whether any of the elements of a are greater than 10
if ( any_of( a.cbegin(), a.cend(), greater10 ) )
cout << "\n\nSome of the elements in a are greater than 10";
else
cout << "\n\nNone of the elements in a are greater than 10";
// determine whether none of the elements of a are greater than 10
if ( none_of( a.cbegin(), a.cend(), greater10 ) )
cout << "\n\nNone of the elements in a are greater than 10";
else
cout << "\n\nSome of the elements in a are greater than 10";
// locate first occurrence of value that's not greater than 10 in a
location = find_if_not( a.cbegin(), a.cend(), greater10 );
if ( location != a.cend() ) // found a value less than or eqaul to 10
cout << "\n\nThe first value not greater than 10 is " << *location
<< "\nfound at location " << ( location - a.cbegin() );
else // no values less than or equal to 10 were found
cout << "\n\nOnly values greater than 10 were found";
cout << endl;
} // end main
// determine whether argument is greater than 10
bool greater10( int value )
{
return value > 10;
} // end function greater10
![输入图片说明](https://static.oschina.net/uploads/img/201704/02211214_A81c.png "在这里输入图片标题") 例6:swap_ranges, sort, merge, unique函数使用示例:
// Fig. 16.7: fig16_07.cpp
// Algorithms iter_swap, swap and swap_ranges.
#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
using namespace std;
// sort using a custom function object
struct {
bool operator()(int a, int b) {
return a > b;
}
} customLess;
int main()
{
const size_t SIZE = 10;
array< int, SIZE > a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
array< int, SIZE > b = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
array<int, 5> c = {15, 13, 11, 9, 7};
ostream_iterator< int > output( cout, " " );
// swap elements in first five elements of array a with
// elements in last five elements of array a
swap_ranges( a.begin(), a.begin() + 5, b.begin() + 5 );
cout << "\nArray a, b after the process: " << endl;
copy( a.cbegin(), a.cend(), output );
cout << endl;
copy( b.cbegin(), b.cend(), output );
cout << endl;
sort(b.begin(), b.end(), std::greater<int>());
copy( b.cbegin(), b.cend(), output );
cout << endl;
vector<int> result;
merge(b.cbegin(), b.cend(), c.cbegin(), c.cend(), back_inserter(result), std::greater<int>());
/Below is also available, but is in C-Style:
merge(b.cbegin(), b.cend(), c.cbegin(), c.cend(), back_inserter(result), customLess);/
cout << "Merge result: ";
copy( result.cbegin(), result.cend(), output );
cout << endl;
auto endLocation = unique(result.begin(), result.end());
for(auto p = endLocation; p <= result.end(); p++)
result.pop_back();
cout << "After unique and reverse, result contains: ";
reverse(result.begin(), result.end());
copy(result.begin(), result.end(), output);
cout << endl;
} // end main
![输入图片说明](https://static.oschina.net/uploads/img/201704/11221910_saw0.png "在这里输入图片标题") 例7:集合操作includes, set_difference, set_intersection, set_symmetric_difference和set_union操作示例:
#include <iostream>
#include <array>
#include <algorithm> // algorithm definitions
#include <iterator> // ostream_iterator
using namespace std;
int main()
{
const size_t SIZE1 = 10, SIZE2 = 5, SIZE3 = 20;
array< int, SIZE1 > a1 = { 1, 2, 2, 4, 5, 6, 7, 8, 9, 10 };
array< int, SIZE2 > a2 = { 4, 5, 6, 7, 8 };
array< int, SIZE2 > a3 = { 4, 5, 6, 11, 15 };
ostream_iterator< int > output( cout, " " );
// determine whether a2 is completely contained in a1
if ( includes( a1.cbegin(), a1.cend(), a2.cbegin(), a2.cend() ) )
cout << "a1 includes a2";
else
cout << "a1 does not include a2";
cout << endl;
// determine whether a3 is completely contained in a1
if ( includes( a1.cbegin(), a1.cend(), a3.cbegin(), a3.cend() ) )
cout << "a1 includes a3";
else
cout << "a1 does not include a3";
cout << "\n" << endl;
array< int, SIZE1 > difference;
// determine elements of a1 not in a2
auto result1 = set_difference( a1.cbegin(), a1.cend(),
a2.cbegin(), a2.cend(), difference.begin() );
cout << "set_difference of a1 and a2 is: ";
copy( difference.begin(), result1, output );
cout << endl;
array< int, SIZE1 > intersection;
// determine elements in both a1 and a2
auto result2 = set_intersection( a1.cbegin(), a1.cend(),
a2.cbegin(), a2.cend(), intersection.begin() );
cout << "set_intersection of a1 and a2 is: ";
copy( intersection.begin(), result2, output );
cout << endl;
array< int, SIZE1 + SIZE2 > symmetric_difference;
// determine elements of a1 that are not in a2 and
// elements of a2 that are not in a1
auto result3 = set_symmetric_difference( a1.cbegin(), a1.cend(),
a3.cbegin(), a3.cend(), symmetric_difference.begin() );
cout << "set_symmetric_difference of a1 and a3 is: ";
copy( symmetric_difference.begin(), result3, output );
cout << endl;
array< int, SIZE3 > unionSet;
// determine elements that are in either or both sets
auto result4 = set_union( a1.cbegin(), a1.cend(),
a3.cbegin(), a3.cend(), unionSet.begin() );
cout << "set_union of a1 and a3 is: ";
copy( unionSet.begin(), result4, output );
cout << endl;
} // end main
![输入图片说明](https://static.oschina.net/uploads/img/201704/13205202_Csvi.png "在这里输入图片标题") 例8:堆有关操作make_heap, sort_heap, push_heap以及pop_heap:
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
const size_t SIZE = 10;
array< int, SIZE > init = { 3, 100, 52, 77, 22, 31, 1, 98, 13, 40 };
array< int, SIZE > a( init ); // copy of init
ostream_iterator< int > output( cout, " " );
make_heap( a.begin(), a.end() ); // create heap from array a
cout << "Array a after make_heap: ";
copy( a.cbegin(), a.cend(), output );
cout << endl;
sort_heap( a.begin(), a.end() ); // sort elements with sort_heap
cout << "Array a after sort_heap: ";
copy( a.cbegin(), a.cend(), output );
cout << endl;
// perform the heapsort with push_heap and pop_heap
cout << "\nArray init contains: ";
copy( init.cbegin(), init.cend(), output ); // display array init
cout << endl;
vector< int > v;
// place elements of array init into v and
// maintain elements of v in heap
for ( size_t i = 0; i < init.size(); ++i )
{
v.push_back( init[ i ] );
push_heap( v.begin(), v.end() );
cout << "\nv after push_heap(init[" << i << "]): ";
copy( v.cbegin(), v.cend(), output );
} // end for
cout << endl;
// remove elements from heap in sorted order
for ( size_t j = 0; j < v.size(); ++j )
{
cout << "\nv after " << v[ 0 ] << " popped from heap\n";
pop_heap( v.begin(), v.end() - j );
copy( v.cbegin(), v.cend(), output );
} // end for
cout << endl;
} // end main
![输入图片说明](https://static.oschina.net/uploads/img/201704/13205844_FYHN.png "在这里输入图片标题") ![输入图片说明](https://static.oschina.net/uploads/img/201704/13205856_qubG.png "在这里输入图片标题") 备注:限于篇幅,本文不详细介绍C++11的is_heap和is_heap_until函数。 参考资料: 1. C++编程官方参考资料cpp reference:URL: http://en.cppreference.com/w/cpp/algorithm 1. 华秋实专栏,fill和generate的区别,URL:http://blog.csdn.net/yockie/article/details/8941649 1. Paul Deitel & Harvey Deitel, C++11程序设计(英文版)(第2版) 1. SamYjy的OSC博客,《一篇文章看懂C++ 标准模板库容器和迭代》
相关文章推荐
- 数组左旋转k位 —— C++标准算法库中最悲剧的函数:rotate
- <<C++标准STL>>读书笔记--算法之比较
- 简化以下程序,将两个 for 循环都替换为标准的 C++ 算法
- 数组左旋转k位 —— C++标准算法库中最悲剧的函数:rotate
- C++标准库和C++标准模版库
- C++之路进阶——优先队列优化最短路径算法(dijkstra)
- C++标准库和C++标准模版库
- 简化以下程序,将函数对象 divide_by 转换为一个函数,并将 for 循环替换为用一个标准的 C++ 算法来输出数据
- C++ STL标准容器插入删除算法的复杂度
- <<C++标准STL>>读书笔记--算法之变动性算法
- 标准C++算数表达式算法
- 第 1 章 第 1 题 高级语言的排序问题 C++标准算法实现
- qt中容器和C++标准模版库(STL)中容器的区别
- 高性能c++之标准模版库
- 数组左旋转k位 —— C++标准算法库中最悲剧的函数:rotate
- 菜鸟进阶:C++实现Chi-square 特征词选择算法
- 8、泛型程序设计与c++标准模板库4.标准c++库中的算法
- C++标准库和C++标准模版库
- C++内存深度克隆(复制)算法启示录(一)
- C++ 11 标准 Lambda表达式