狂自私

导航

C++复习:STL之算法

算法

1算法基础

1.1算法概述

  • 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成。
  • <algorithm>是所有STL头文件中最大的一个,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、反转、排序、合并等等。
  • <numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
  • <functional>中则定义了一些模板类,用以声明函数对象。
  • STL提供了大量实现算法的模版函数,只要我们熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能,从而大大地提升效率。
  • #include <algorithm>
  • #include <numeric>
  • #include <functional>

1.2 STL中算法分类

  • 操作对象
    • 直接改变容器的内容
    • 将原容器的内容复制一份,修改其副本,然后传回该副本
  • 功能:
    • 非可变序列算法 指不直接修改其所操作的容器内容的算法
      • 计数算法     count、count_if
      • 搜索算法     search、find、find_if、find_first_of、…
      • 比较算法     equal、mismatch、lexicographical_compare
    • 可变序列算法 指可以修改它们所操作的容器内容的算法
      • 删除算法     remove、remove_if、remove_copy、…
      • 修改算法     for_each、transform
      • 排序算法     sort、stable_sort、partial_sort、
    • 排序算法 包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作
    • 数值算法 对容器内容进行数值计算

 

1.3查找算法(13个):判断容器中是否包含某个值

函数名

头文件

函数功能

adjacent_find 

<algorithm> 

在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的ForwardIterator .否则返回last.重载版本使用输入的二元操作符代替相等的判断

函数原形

template<class FwdIt> FwdIt adjacent_find(FwdIt first, FwdIt last); 

template<class FwdIt, class Pred> FwdIt adjacent_find(FwdIt first, FwdIt last, Pred pr);

binary_search 

<algorithm> 

在有序序列中查找value,找到返回true.重载的版本实用指定的比较函数对象或函数指针来判断相等

函数原形

template<class FwdIt, class T> bool binary_search(FwdIt first, FwdIt last, const T& val); 

template<class FwdIt, class T, class Pred> bool binary_search(FwdIt first, FwdIt last, const T& val,Pred pr);

count 

<algorithm> 

利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数

函数原形

template<class InIt, class Dist> size_t count(InIt first, InIt last,const T& val, Dist& n); 

count_if

<algorithm> 

利用输入的操作符,对标志范围内的元素进行操作,返回结果为true的个数

函数原形

template<class InIt, class Pred, class Dist> size_t count_if(InIt first, InIt last, Pred pr); 

equal_range 

<algorithm> 

功能类似equal,返回一对iterator,第一个表示lower_bound,第二个表示upper_bound

函数原形

template<class FwdIt, class T> pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,const T& val);

template<class FwdIt, class T, class Pred> pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,const T& val, Pred pr); 

find 

<algorithm> 

利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较.当匹配时,结束搜索,返回该元素的一个InputIterator

函数原形

template<class InIt, class T> InIt find(InIt first, InIt last, const T& val); 

find_end 

<algorithm> 

在指定范围内查找"由输入的另外一对iterator标志的第二个序列"的最后一次出现.找到则返回最后一对的第一个ForwardIterator,否则返回输入的"另外一对"的第一个ForwardIterator.重载版本使用用户输入的操作符代替等于操作

函数原形

template<class FwdIt1, class FwdIt2> FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2); 

template<class FwdIt1, class FwdIt2, class Pred> FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2, Pred pr);

find_first_of 

<algorithm> 

在指定范围内查找"由输入的另外一对iterator标志的第二个序列"中任意一个元素的第一次出现。重载版本中使用了用户自定义操作符

函数原形

template<class FwdIt1, class FwdIt2> FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2); 

template<class FwdIt1, class FwdIt2, class Pred> FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2, Pred pr);

find_if 

<algorithm> 

使用输入的函数代替等于操作符执行find

  

template<class InIt, class Pred> InIt find_if(InIt first, InIt last, Pred pr); 

lower_bound 

<algorithm>

返回一个ForwardIterator,指向在有序序列范围内的可以插入指定值而不破坏容器顺序的第一个位置.重载函数使用自定义比较操作

函数原形

template<class FwdIt, class T> FwdIt lower_bound(FwdIt first, FwdIt last, const T& val); 

template<class FwdIt, class T, class Pred> FwdIt lower_bound(FwdIt first, FwdIt last, const T& val, Pred pr);

upper_bound 

<algorithm> 

返回一个ForwardIterator,指向在有序序列范围内插入value而不破坏容器顺序的最后一个位置,该位置标志一个大于value的值.重载函数使用自定义比较操作

函数原形

template<class FwdIt, class T> FwdIt upper_bound(FwdIt first, FwdIt last, const T& val); 

template<class FwdIt, class T, class Pred> FwdIt upper_bound(FwdIt first, FwdIt last, const T& val, Pred pr);

search 

<algorithm> 

给出两个范围,返回一个ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向last1,重载版本使用自定义的比较操作

函数原形

template<class FwdIt1, class FwdIt2> FwdIt1 search(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2);

template<class FwdIt1, class FwdIt2, class Pred> FwdIt1 search(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2, Pred pr); 

search_n 

<algorithm> 

在指定范围内查找val出现n次的子序列。重载版本使用自定义的比较操作

函数原形

template<class FwdIt, class Dist, class T> FwdIt search_n(FwdIt first, FwdIt last,Dist n, const T& val);

template<class FwdIt, class Dist, class T, class Pred> FwdIt search_n(FwdIt first, FwdIt last,Dist n, const T& val, Pred pr); 

 

1.4堆算法(4个)

函数名

头文件

函数功能

make_heap

<algorithm>

把指定范围内的元素生成一个堆。重载版本使用自定义比较操作

函数原形

template<class RanIt> void make_heap(RanIt first, RanIt last);

template<class RanIt, class Pred> void make_heap(RanIt first, RanIt last, Pred pr);

pop_heap

<algorithm>

并不真正把最大元素从堆中弹出,而是重新排序堆。它把first和last-1交换,然后重新生成一个堆。可使用容器的back来访问被"弹出"的元素或者使用pop_back进行真正的删除。重载版本使用自定义的比较操作

函数原形

template<class RanIt> void pop_heap(RanIt first, RanIt last);

template<class RanIt, class Pred> void pop_heap(RanIt first, RanIt last, Pred pr);

push_heap

<algorithm>

假设first到last-1是一个有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向该函数前,必须先把元素插入容器后。重载版本使用指定的比较操作

函数原形

template<class RanIt>void push_heap(RanIt first, RanIt last);

template<class RanIt, class Pred> void push_heap(RanIt first, RanIt last, Pred pr);

sort_heap

<algorithm>

对指定范围内的序列重新排序,它假设该序列是个有序堆。重载版本使用自定义比较操作

函数原形

template<class RanIt> void sort_heap(RanIt first, RanIt last);

template<class RanIt, class Pred> void sort_heap(RanIt first, RanIt last, Pred pr);

1.5关系算法(8个)

函数名

头文件

函数功能

equal 

<algorithm> 

如果两个序列在标志范围内元素都相等,返回true。重载版本使用输入的操作符代替默认的等于操作符

函数原形

template<class InIt1, class InIt2> bool equal(InIt1 first, InIt1 last, InIt2 x); 

template<class InIt1, class InIt2, class Pred> bool equal(InIt1 first, InIt1 last, InIt2 x, Pred pr); 

includes 

<algorithm>

判断第一个指定范围内的所有元素是否都被第二个范围包含,使用底层元素的<操作符,成功返回true。重载版本使用用户输入的函数

函数原形

template<class InIt1, class InIt2> bool includes(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2); 

template<class InIt1, class InIt2, class Pred> bool includes(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2, Pred pr);

lexicographical_compare 

<algorithm> 

比较两个序列。重载版本使用用户自定义比较操作

函数原形

template<class InIt1, class InIt2> bool lexicographical_compare(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2); 

template<class InIt1, class InIt2, class Pred> bool lexicographical_compare(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2, Pred pr);

max 

<algorithm> 

返回两个元素中较大一个。重载版本使用自定义比较操作

函数原形

template<class T> const T& max(const T& x, const T& y); 

template<class T, class Pred> const T& max(const T&  x, const T& y, Pred pr);

max_element 

<algorithm> 

返回一个ForwardIterator,指出序列中最大的元素。重载版本使用自定义比较操作

函数原形

template<class FwdIt> FwdIt max_element(FwdIt first, FwdIt last); 

template<class FwdIt, class Pred> FwdIt max_element(FwdIt first, FwdIt last, Pred pr);

min 

<algorithm> 

返回两个元素中较小一个。重载版本使用自定义比较操作

函数原形

template<class T> const T& min(const T& x, const T& y); 

template<class T, class Pred> const T& min(const T& x, const T& y, Pred pr); 

min_element 

<algorithm> 

返回一个ForwardIterator,指出序列中最小的元素。重载版本使用自定义比较操作

函数原形

template<class FwdIt> FwdIt min_element(FwdIt first, FwdIt last); 

template<class FwdIt, class Pred> FwdIt min_element(FwdIt first, FwdIt last, Pred pr); 

mismatch 

<algorithm> 

并行比较两个序列,指出第一个不匹配的位置,返回一对iterator,标志第一个不匹配元素位置。如果都匹配,返回每个容器的last。重载版本使用自定义的比较操作

函数原形

template<class InIt1, class InIt2> pair<InIt1, InIt2> mismatch(InIt1 first, InIt1 last, InIt2 x); 

template<class InIt1, class InIt2, class Pred> pair<InIt1, InIt2> mismatch(InIt1 first, InIt1 last, InIt2 x, Pred pr);

 

1.6集合算法(4个)

函数名

头文件

函数功能

set_union

<algorithm>

构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作

函数原形

template<class InIt1, class InIt2, class OutIt> OutIt set_union(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x);

template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_union(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2,OutIt x, Pred pr);

set_intersection

<algorithm>

构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作

函数原形

template<class InIt1, class InIt2, class OutIt> OutIt set_intersection(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2, OutIt x);

template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_intersection(InIt1 first1, InIt1 last1,InIt2 first2,InIt2 last2, OutIt x, Pred pr);

set_difference

<algorithm>

构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作

函数原形

template<class InIt1, class InIt2, class OutIt> OutIt set_difference(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2, OutIt x);

template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr);

set_symmetric_difference

<algorithm>

构造一个有序序列,该序列取两个序列的对称差集(并集-交集)

函数原形

template<class InIt1, class InIt2, class OutIt> OutIt set_symmetric_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x);

template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_symmetric_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr);

 

1.6列组合算法(2个)

提供计算给定集合按一定顺序的所有可能排列组合

函数名

头文件

函数功能

next_permutation

<algorithm>

取出当前范围内的排列,并重新排序为下一个排列。重载版本使用自定义的比较操作

函数原形

template<class BidIt> bool next_permutation(BidIt first, BidIt last);

template<class BidIt, class Pred> bool next_permutation(BidIt first, BidIt last, Pred pr);

prev_permutation

<algorithm>

 取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回false。重载版本使用自定义的比较操作

函数原形

template<class BidIt> bool prev_permutation(BidIt first, BidIt last);

template<class BidIt, class Pred> bool prev_permutation(BidIt first, BidIt last, Pred pr);

1.7排序和通用算法(14个):提供元素排序策略

函数名

头文件

函数功能

inplace_merge

<algorithm>

合并两个有序序列,结果序列覆盖两端范围。重载版本使用输入的操作进行排序

函数原形

template<class BidIt> void inplace_merge(BidIt first, BidIt middle, BidIt last);

template<class BidIt, class Pred> void inplace_merge(BidIt first, BidIt middle, BidIt last, Pred pr);

merge

<algorithm>

合并两个有序序列,存放到另一个序列。重载版本使用自定义的比较

函数原形

template<class InIt1, class InIt2, class OutIt> OutIt merge(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2, OutIt x);

template<class InIt1, class InIt2, class OutIt, class Pred> OutIt merge(InIt1 first1, InIt1 last1,InIt2 first2, InIt2 last2, OutIt x, Pred pr);

nth_element

<algorithm>

将范围内的序列重新排序,使所有小于第n个元素的元素都出现在它前面,而大于它的都出现在后面。重载版本使用自定义的比较操作

函数原形

template<class RanIt> void nth_element(RanIt first, RanIt nth, RanIt last);

template<class RanIt, class Pred> void nth_element(RanIt first, RanIt nth, RanIt last, Pred pr);

partial_sort

<algorithm>

对序列做部分排序,被排序元素个数正好可以被放到范围内。重载版本使用自定义的比较操作

函数原形

template<class RanIt> void partial_sort(RanIt first, RanIt middle, RanIt last);

template<class RanIt, class Pred> void partial_sort(RanIt first, RanIt middle, RanIt last, Pred pr);

partial_sort_copy

<algorithm>

与partial_sort类似,不过将经过排序的序列复制到另一个容器

函数原形

template<class InIt, class RanIt> RanIt partial_sort_copy(InIt first1, InIt last1,RanIt first2, RanIt last2);

template<class InIt, class RanIt, class Pred> RanIt partial_sort_copy(InIt first1, InIt last1,RanIt first2, RanIt last2, Pred pr);

partition

<algorithm>

对指定范围内元素重新排序,使用输入的函数,把结果为true的元素放在结果为false的元素之前

函数原形

template<class BidIt, class Pred> BidIt partition(BidIt first, BidIt last, Pred pr);

random_shuffle

<algorithm>

对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作

函数原形

template<class RanIt> void random_shuffle(RanIt first, RanIt last);

template<class RanIt, class Fun> void random_shuffle(RanIt first, RanIt last, Fun& f);

reverse

<algorithm>

将指定范围内元素重新反序排序

函数原形

template<class BidIt> void reverse(BidIt first, BidIt last);

reverse_copy

<algorithm>

与reverse类似,不过将结果写入另一个容器

函数原形

template<class BidIt, class OutIt> OutIt reverse_copy(BidIt first, BidIt last, OutIt x);

rotate

<algorithm>

将指定范围内元素移到容器末尾,由middle指向的元素成为容器第一个元素

函数原形

template<class FwdIt> void rotate(FwdIt first, FwdIt middle, FwdIt last);

rotate_copy

<algorithm>

与rotate类似,不过将结果写入另一个容器

函数原形

template<class FwdIt, class OutIt> OutIt rotate_copy(FwdIt first, FwdIt middle, FwdIt last, OutIt x);

sort

<algorithm>

以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作

函数原形

template<class RanIt> void sort(RanIt first, RanIt last);

template<class RanIt, class Pred> void sort(RanIt first, RanIt last, Pred pr);

stable_sort

<algorithm>

与sort类似,不过保留相等元素之间的顺序关系

函数原形

template<class BidIt> void stable_sort(BidIt first, BidIt last);

template<class BidIt, class Pred> void stable_sort(BidIt first, BidIt last, Pred pr);

stable_partition

<algorithm>

与partition类似,不过不保证保留容器中的相对顺序

函数原形

template<class FwdIt, class Pred> FwdIt stable_partition(FwdIt first, FwdIt last, Pred pr);

 

1.8删除和替换算法(15个)

函数名

头文件

函数功能

copy

<algorithm>

复制序列

函数原形

template<class InIt, class OutIt> OutIt copy(InIt first, InIt last, OutIt x);

copy_backward

<algorithm>

与copy相同,不过元素是以相反顺序被拷贝

函数原形

template<class BidIt1, class BidIt2> BidIt2 copy_backward(BidIt1 first, BidIt1 last, BidIt2 x);

iter_swap

<algorithm>

交换两个ForwardIterator的值

函数原形

template<class FwdIt1, class FwdIt2> void iter_swap(FwdIt1 x, FwdIt2 y);

remove

<algorithm>

删除指定范围内所有等于指定元素的元素。注意,该函数不是真正删除函数。内置函数不适合使用remove和remove_if函数

函数原形

template<class FwdIt, class T> FwdIt remove(FwdIt first, FwdIt last, const T& val);

remove_copy

<algorithm>

将所有不匹配元素复制到一个制定容器,返回OutputIterator指向被拷贝的末元素的下一个位置

函数原形

template<class InIt, class OutIt, class T> OutIt remove_copy(InIt first, InIt last, OutIt x, const T& val);

remove_if

<algorithm>

删除指定范围内输入操作结果为true的所有元素

函数原形

template<class FwdIt, class Pred> FwdIt remove_if(FwdIt first, FwdIt last, Pred pr);

remove_copy_if

<algorithm>

将所有不匹配元素拷贝到一个指定容器

函数原形

template<class InIt, class OutIt, class Pred> OutIt remove_copy_if(InIt first, InIt last, OutIt x, Pred pr);

replace

<algorithm>

将指定范围内所有等于vold的元素都用vnew代替

函数原形

template<class FwdIt, class T> void replace(FwdIt first, FwdIt last,const T& vold, const T& vnew);

replace_copy

<algorithm>

与replace类似,不过将结果写入另一个容器

函数原形

template<class InIt, class OutIt, class T> OutIt replace_copy(InIt first, InIt last, OutIt x,const T& vold, const T& vnew);

replace_if

<algorithm>

将指定范围内所有操作结果为true的元素用新值代替

函数原形

template<class FwdIt, class Pred, class T> void replace_if(FwdIt first, FwdIt last,Pred pr, const T& val);

replace_copy_if

<algorithm>

与replace_if,不过将结果写入另一个容器

函数原形

template<class InIt, class OutIt, class Pred, class T> OutIt replace_copy_if(InIt first, InIt last, OutIt x, Pred pr, const T& val);

swap

<algorithm>

交换存储在两个对象中的值

函数原形

template<class T> void swap(T& x, T& y);

swap_range

<algorithm>

将指定范围内的元素与另一个序列元素值进行交换

函数原形

template<class FwdIt1, class FwdIt2> FwdIt2 swap_ranges(FwdIt1 first, FwdIt1 last, FwdIt2 x);

unique

<algorithm>

清除序列中重复元素,和remove类似,它也不能真正删除元素。重载版本使用自定义比较操作

函数原形

template<class FwdIt> FwdIt unique(FwdIt first, FwdIt last);

template<class FwdIt, class Pred> FwdIt unique(FwdIt first, FwdIt last, Pred pr);

unique_copy

<algorithm>

与unique类似,不过把结果输出到另一个容器

函数原形

template<class InIt, class OutIt> OutIt unique_copy(InIt first, InIt last, OutIt x);

template<class InIt, class OutIt, class Pred> OutIt unique_copy(InIt first, InIt last, OutIt x, Pred pr);

 

1.9生成和变异算法(6个)

函数名

头文件

函数功能

fill

<algorithm>

将输入值赋给标志范围内的所有元素

函数原形

template<class FwdIt, class T> void fill(FwdIt first, FwdIt last, const T& x);

fill_n

<algorithm>

将输入值赋给first到first+n范围内的所有元素

函数原形

template<class OutIt, class Size, class T> void fill_n(OutIt first, Size n, const T& x);

for_each

<algorithm>

用指定函数依次对指定范围内所有元素进行迭代访问,返回所指定的函数类型。该函数不得修改序列中的元素

函数原形

template<class InIt, class Fun> Fun for_each(InIt first, InIt last, Fun f);

generate

<algorithm>

连续调用输入的函数来填充指定的范围

函数原形

template<class FwdIt, class Gen> void generate(FwdIt first, FwdIt last, Gen g);

generate_n

<algorithm>

与generate函数类似,填充从指定iterator开始的n个元素

函数原形

template<class OutIt, class Pred, class Gen> void generate_n(OutIt first, Dist n, Gen g);

transform

<algorithm>

将输入的操作作用与指定范围内的每个元素,并产生一个新的序列。重载版本将操作作用在一对元素上,另外一个元素来自输入的另外一个序列。结果输出到指定容器

函数原形

template<class InIt, class OutIt, class Unop> OutIt transform(InIt first, InIt last, OutIt x, Unop uop);

template<class InIt1, class InIt2, class OutIt, class Binop> OutIt transform(InIt1 first1, InIt1 last1, InIt2 first2,OutIt x, Binop bop);

1.10算数算法(4个)

函数名

头文件

函数功能

accumulate

<numeric>

iterator对标识的序列段元素之和,加到一个由val指定的初始值上。重载版本不再做加法,而是传进来的二元操作符被应用到元素上

函数原形

template<class InIt, class T> T accumulate(InIt first, InIt last, T val);

template<class InIt, class T, class Pred> T accumulate(InIt first, InIt last, T val, Pred pr);

partial_sum

<numeric>

创建一个新序列,其中每个元素值代表指定范围内该位置前所有元素之和。重载版本使用自定义操作代替加法

函数原形

template<class InIt, class OutIt> OutIt partial_sum(InIt first, InIt last,OutIt result);

template<class InIt, class OutIt, class Pred> OutIt partial_sum(InIt first, InIt last,OutIt result, Pred pr);

product

<numeric>

对两个序列做内积(对应元素相乘,再求和)并将内积加到一个输入的初始值上。重载版本使用用户定义的操作

函数原形

template<class InIt1, class InIt2, class T> T product(InIt1 first1, InIt1 last1,Init2 first2, T val);

template<class InIt1, class InIt2, class T,class Pred1, class Pred2> T product(InIt1 first1, InIt1 last1,Init2 first2, T val, Pred1 pr1, Pred2 pr2);

adjacent_difference

<numeric>

创建一个新序列,新序列中每个新值代表当前元素与上一个元素的差。重载版本用指定二元操作计算相邻元素的差

函数原形

template<class InIt, class OutIt> OutIt adjacent_difference(InIt first, InIt last,OutIt result);

template<class InIt, class OutIt, class Pred> OutIt adjacent_difference(InIt first, InIt last,OutIt result, Pred pr);

 

1.11常用算法汇总

adjacent_find()( adjacent 是邻近的意思),binary_search(),count(),

count_if(),equal_range(),find(),find_if()

merge(),sort(),random_shuffle()(shuffle是洗牌的意思) ,reverse()。

copy(), replace(),

replace_if(),swap()

accumulate()( accumulate 是求和的意思),fill(),。

set_union(),set_intersection(),

set_difference()。

for_each(), transform()( transform 是变换的意思)

2STL算法中函数对象和谓词

2.1函数对象和谓词定义

函数对象:

重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象。一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)"的方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。

这是通过重载类的operator()来实现的。

"在标准库中,函数对象被广泛地使用以获得弹性",标准库中的很多算法都可以使用函数对象或者函数来作为自定的回调行为

谓词:

一元函数对象:函数参数1个;

二元函数对象:函数参数2个;

一元谓词 函数参数1个,函数返回值是bool类型,可以作为一个判断式

            谓词可以使一个仿函数,也可以是一个回调函数。

二元谓词 函数参数2个,函数返回值是bool类型

 

一元谓词函数举例如下

1,判断给出的string对象的长度是否小于6

bool GT6(const string &s)

{

return s.size() >= 6;

}

2,判断给出的int是否在3到8之间

bool Compare( int i )

{

return ( i >= 3 && i <= 8 );

}

二元谓词举例如下

1,比较两个string对象,返回一个bool值,指出第一个string是否比第二个短

bool isShorter(const string &s1, const string &s2)

{

return s1.size() < s2.size();

}

2.2一元函数对象案例

//1普通类 重载 函数调用操作符

template <typename T>

void FuncShowElemt(T &t) //普通函数 不能像 仿函数那样记录状态

{

    cout << t << " ";

};

 

void showChar(char &t)

{

    cout << t << " ";

}

 

//函数模板 重载 函数调用操作符

template <typename T>

class ShowElemt

{

public:

    ShowElemt()

    {

        n = 0;

    }

    void operator()(T &t)

    {

        n++;

        cout << t << " ";

    }

    void printCount()

    {

        cout << n << endl;

    }

public:

    int n;

};

 

//1 函数对象 基本使用

void main11()

{

    int a = 100;

    FuncShowElemt<int>(a); //普通的函数调用

 

    ShowElemt<int> showElemt; //函数对象

    showElemt(a); //函数对象调用

}

2.3一元谓词案例

//1元谓词 例子

template <typename T>

class Isdiv

{

public:

    Isdiv(const T &divisor) //

    {

        this->divisor = divisor;

    }

    bool operator()(T &t)

    {

        return (t%divisor == 0);

    }

protected:

private:

    T divisor;

};

 

void main13()

{

    vector<int> v2;

    for (int i=10; i<33; i++)

    {

        v2.push_back(i);

    }

    vector<int>::iterator it;

    int a = 4;

    Isdiv<int> mydiv(a);

    // _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) //返回的是迭代器

    it = find_if(v2.begin(), v2.end(), Isdiv<int>(4));

    if (it != v2.end())

    {

        cout << "第一个被4整除的数是:" << *it << endl;

    }

}

 

2.4二元函数对象案例

template <typename T>

struct SumAdd

{

    T operator()(T &t1, T &t2)

    {

        return t1 + t2;

    }

};

 

template <typename T>

void printE(T &t)

{

    for (vector<int>::iterator it = t.begin(); it!=t.end(); it++ )

    {

        cout << *it << " ";

    }

}

 

void printVector(vector<int> &v)

{

    for (vector<int>::iterator it = v.begin(); it!=v.end(); it++ )

    {

        cout << *it << " ";

    }

}

 

void main14()

{

    vector<int> v1, v2 ;

    vector<int> v3;

    v1.push_back(1);

    v1.push_back(2);

    v1.push_back(3);

 

    v2.push_back(4);

    v2.push_back(5);

    v2.push_back(6);

 

    v3.resize(10);

 

    //transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());

    /*

    template<class _InIt1,

    class _InIt2,

    class _OutIt,

    class _Fn2> inline

        _OutIt transform(_InIt1 _First1, _InIt1 _Last1,

        _InIt2 _First2, _OutIt _Dest, _Fn2 _Func)

    */

    vector<int>::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());

    cout << *it << endl;

    printE(v3);    

}

 

2.5二元谓词案例

void current(int &v)

{

    cout << v << " ";

}

 

bool MyCompare(const int &a, const int &b)

{

    return a < b;

}

void main15()

{

    vector<int> v(10);

 

    for (int i=0; i<10; i++)

    {

        v[i] = rand() % 100;

    }

 

    for_each(v.begin(), v.end(), current);

    printf("\n");

    sort(v.begin(), v.end(), MyCompare );

 

    printf("\n");

    for (int i=0; i<10; i++)

    {

        printf("%d ", v[i]);

    }

    printf("\n");

}

2.6预定义函数对象和函数适配器

1)预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含。

//1使用预定义函数对象:

//类模板plus<> 的实现了: 不同类型的数据进行加法运算

void main41()

{

    plus<int> intAdd;

    int x = 10;

    int y = 20;

    int z = intAdd(x, y); //等价于 x + y

    cout << z << endl;

 

    plus<string> stringAdd;

    string myc = stringAdd("aaa", "bbb");

    cout << myc << endl;

 

    vector<string> v1;

    v1.push_back("bbb");

    v1.push_back("aaa");

    v1.push_back("ccc");

    v1.push_back("zzzz");

 

    //缺省情况下,sort()用底层元素类型的小于操作符以升序排列容器的元素。

    //为了降序,可以传递预定义的类模板greater,它调用底层元素类型的大于操作符:

    cout << "sort()函数排序" << endl;;

    sort(v1.begin(), v1.end(), greater<string>() ); //从大到小

    for (vector<string>::iterator it=v1.begin(); it!=v1.end(); it++ )

    {

        cout << *it << endl;

    }

}

2)算术函数对象

预定义的函数对象支持加、减、乘、除、求余和取反。调用的操作符是与type相关联的实例

加法:plus<Types>

plus<string> stringAdd;

sres = stringAdd(sva1,sva2);

减法:minus<Types>

乘法:multiplies<Types>

除法divides<Tpye>

求余:modulus<Tpye>

取反:negate<Type>

negate<int> intNegate;

ires = intNegate(ires);

Ires= UnaryFunc(negate<int>(),Ival1);

 

3)关系函数对象

等于equal_to<Tpye>

equal_to<string> stringEqual;

sres = stringEqual(sval1,sval2);

不等于not_equal_to<Type>

大于 greater<Type>

大于等于greater_equal<Type>

小于 less<Type>

小于等于less_equal<Type>

 

void main42()

{

    vector<string> v1;

    v1.push_back("bbb");

    v1.push_back("aaa");

    v1.push_back("ccc");

    v1.push_back("zzzz");

    v1.push_back("ccc");

    string s1 = "ccc";

    //int num = count_if(v1.begin(),v1.end(), equal_to<string>(),s1);

    int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(), s1));

    cout << num << endl;

}

 

4)逻辑函数对象

逻辑与 logical_and<Type>

logical_and<int> indAnd;

ires = intAnd(ival1,ival2);

dres=BinaryFunc( logical_and<double>(),dval1,dval2);

逻辑或logical_or<Type>

逻辑非logical_not<Type>

logical_not<int> IntNot;

Ires = IntNot(ival1);

Dres=UnaryFunc( logical_not<double>,dval1);

2.7函数适配器

1)函数适配器的理论知识

 

2)常用函数函数适配器

标准库提供一组函数适配器,用来特殊化或者扩展一元和二元函数对象。常用适配器是:

1绑定器(binder): binder通过把二元函数对象的一个实参绑定到一个特殊的值上,将其转换成一元函数对象。C++标准库提供两种预定义的binder适配器:bind1st和bind2nd,前者把值绑定到二元函数对象的第一个实参上,后者绑定在第二个实参上。

2取反器(negator) : negator是一个将函数对象的值翻转的函数适配器。标准库提供两个预定义的ngeator适配器:not1翻转一元预定义函数对象的真值,而not2翻转二元谓词函数的真值。

常用函数适配器列表如下:

bind1st(op, value)

bind2nd(op, value)

not1(op)

not2(op)

mem_fun_ref(op)

mem_fun(op)

ptr_fun(op)

3)常用函数适配器案例

//////////////////////////////////////////////////////////////////////////

class IsGreat

{

public:

    IsGreat(int i)

    {

        m_num = i;

    }

    bool operator()(int &num)

    {

        if (num > m_num)

        {

            return true;

        }

        return false;

    }

protected:

private:

    int m_num;

};

 

void main43()

{

    vector<int> v1;

    for (int i=0; i<5; i++)

    {

        v1.push_back(i+1);

    }

 

    for (vector<int>::iterator it = v1.begin(); it!=v1.end(); it ++)

    {

        cout << *it << " " ;

    }

 

    int num1 = count(v1.begin(), v1.end(), 3);

    cout << "num1:" << num1 << endl;

 

    //通过谓词求大于2的个数

    int num2 = count_if(v1.begin(), v1.end(), IsGreat(2));

    cout << "num2:" << num2 << endl;

 

    //通过预定义函数对象求大于2的个数 greater<int>() 有2个参数

    //                                                param > 2

    int num3 = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(), 2 ) );

    cout << "num3:" << num3 << endl;

 

    //取模 能被2整除的数 求奇数

    int num4 = count_if(v1.begin(), v1.end(), bind2nd(modulus <int>(), 2 ) );

    cout << "奇数num4:" << num4 << endl;

 

    int num5 = count_if(v1.begin(), v1.end(), not1( bind2nd(modulus <int>(), 2 ) ) );

    cout << "偶数num5:" << num5 << endl;

    return ;

}

 

2.8 STL的容器算法迭代器的设计理念

  1. STL的容器通过类模板技术,实现数据类型和容器模型的分离。
  2. STL的迭代器技术实现了遍历容器的统一方法;也为STL的算法提供了统一性
  3. STL的函数对象实现了自定义数据类型的算法运算。(算法和)
  4. 具体例子:transform算法的输入,通过迭代器first和last指向的元算作为输入;通过result作为输出;通过函数对象来做自定义数据类型的运算。

3常用的查找算法

adjacent_find()

在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器。否则返回past-the-end。

vector<int> vecInt;

    vecInt.push_back(1);

    vecInt.push_back(2);

    vecInt.push_back(2);

    vecInt.push_back(4);

    vecInt.push_back(5);

vecInt.push_back(5);

 

    vector<int>::iterator it = adjacent_find(vecInt.begin(), vecInt.end());        //*it == 2

binary_search

在有序序列中查找value,找到则返回true。注意:在无序序列中,不可使用。

 

        set<int> setInt;

        setInt.insert(3);

        setInt.insert(1);

        setInt.insert(7);

        setInt.insert(5);

        setInt.insert(9);

 

        bool bFind = binary_search(setInt.begin(),setInt.end(),5);

count()

利用等于操作符,把标志范围内的元素与输入值比较,返回相等的个数。

vector<int> vecInt;

        vecInt.push_back(1);

        vecInt.push_back(2);

        vecInt.push_back(2);

        vecInt.push_back(4);

        vecInt.push_back(2);

        vecInt.push_back(5);

        int iCount = count(vecInt.begin(),vecInt.end(),2);    //iCount==3

    

count_if()

假设vector<int> vecIntA,vecIntA包含1,3,5,7,9元素

 

//先定义比较函数

bool GreaterThree(int iNum)

{

        if(iNum>=3)

        {

            return true;

        }

        else

        {

            return false;

        }

}

 

int iCount = count_if(vecIntA.begin(), vecIntA.end(), GreaterThree);

//此时iCount == 4

find()

  • find: 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的迭代器。
  • equal_range: 返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。

 

vector<int> vecInt;

        vecInt.push_back(1);

        vecInt.push_back(3);

        vecInt.push_back(5);

        vecInt.push_back(7);

        vecInt.push_back(9);

 

vector<int>::iterator it = find(vecInt.begin(), vecInt.end(), 5);        //*it == 5

find_if()

find_if: 使用输入的函数代替等于操作符执行find。返回被找到的元素的迭代器。

假设vector<int> vecIntA,vecIntA包含1,3,5,3,9元素

vector<int>::it = find_if(vecInt.begin(),vecInt.end(),GreaterThree);

此时 *it==3, *(it+1)==5, *(it+2)==3, *(it+3)==9

 

4常用的排序算法

merge()

  • 以下是排序和通用算法:提供元素排序策略
  • merge: 合并两个有序序列,存放到另一个序列。

例如:vecIntA,vecIntB,vecIntC是用vector<int>声明的容器,vecIntA已包含1,3,5,7,9元素,vecIntB已包含2,4,6,8元素

vecIntC.resize(9); //扩大容量

merge(vecIntA.begin(),vecIntA.end(),vecIntB.begin(),vecIntB.end(),vecIntC.begin());

此时vecIntC就存放了按顺序的1,2,3,4,5,6,7,8,9九个元素

sort()

  • sort: 以默认升序的方式重新排列指定范围内的元素。若要改排序规则,可以输入比较函数。

//学生类

Class CStudent:

{

public:

CStudent(int iID, string strName)

        {

m_iID=iID;

m_strName=strName;

}

public:

    int m_iID;

    string m_strName;

}

 

//学号比较函数

bool Compare(const CStudent &stuA,const CStudent &stuB)

{

         return (stuA.m_iID<strB.m_iID);

}

void main()

{

vector<CStudent> vecStu;

vecStu.push_back(CStudent(2,"老二"));

vecStu.push_back(CStudent(1,"老大"));

vecStu.push_back(CStudent(3,"老三"));

vecStu.push_back(CStudent(4,"老四"));

 

sort(vecStu.begin(),vecStu.end(),Compare);

 

// 此时,vecStu容器包含了按顺序的"老大对象","老二对象","老三对象","老四对象"

}

random_shuffle()

  • random_shuffle: 对指定范围内的元素随机调整次序。

        srand(time(0));            //设置随机种子

 

        vector<int> vecInt;

        vecInt.push_back(1);

        vecInt.push_back(3);

        vecInt.push_back(5);

        vecInt.push_back(7);

        vecInt.push_back(9);

 

        string str("itcastitcast ");

      

        random_shuffle(vecInt.begin(), vecInt.end()); //随机排序,结果比如:9,7,1,5,3

        random_shuffle(str.begin(), str.end());         //随机排序,结果比如:" itstcasticat "

reverse()

        vector<int> vecInt;

        vecInt.push_back(1);

        vecInt.push_back(3);

        vecInt.push_back(5);

        vecInt.push_back(7);

        vecInt.push_back(9);

 

        reverse(vecInt.begin(), vecInt.end());        //{9,7,5,3,1}

5常用的拷贝和替换算法

copy()

vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        vecIntA.push_back(7);

        vecIntA.push_back(9);

 

        vector<int> vecIntB;

        vecIntB.resize(5);            //扩大空间

 

        copy(vecIntA.begin(), vecIntA.end(), vecIntB.begin());    //vecIntB: {1,3,5,7,9}

replace()

  • replace(beg,end,oldValue,newValue): 将指定范围内的所有等于oldValue的元素替换成newValue。

        vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        vecIntA.push_back(3);

        vecIntA.push_back(9);

 

        replace(vecIntA.begin(), vecIntA.end(), 3, 8);        //{1,8,5,8,9}

replace_if()

  • replace_if : 将指定范围内所有操作结果为true的元素用新值替换。

用法举例:

replace_if(vecIntA.begin(),vecIntA.end(),GreaterThree,newVal)

其中 vecIntA是用vector<int>声明的容器

GreaterThree 函数的原型是 bool GreaterThree(int iNum)

 

//把大于等于3的元素替换成8

        vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        vecIntA.push_back(3);

        vecIntA.push_back(9);

 

        replace_if(vecIntA.begin(), vecIntA.end(), GreaterThree, 8);        // GreaterThree的定义在上面。

swap()

  • swap: 交换两个容器的元素

        vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        

        vector<int> vecIntB;

        vecIntB.push_back(2);

        vecIntB.push_back(4);

 

        swap(vecIntA, vecIntB); //交换

6常用的算术和生成算法

accumulate()

  • accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。
  • #include<numeric>

        vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        vecIntA.push_back(7);

        vecIntA.push_back(9);

        int iSum = accumulate(vecIntA.begin(), vecIntA.end(), 100);        //iSum==125

fill()

  • fill: 将输入值赋给标志范围内的所有元素。

        vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        vecIntA.push_back(7);

        vecIntA.push_back(9);

        fill(vecIntA.begin(), vecIntA.end(), 8);        //8, 8, 8, 8, 8

7常用的集合算法

set_union(),set_intersection(),set_difference()

  • set_union: 构造一个有序序列,包含两个有序序列的并集。
  • set_intersection: 构造一个有序序列,包含两个有序序列的交集。
  • set_difference: 构造一个有序序列,该序列保留第一个有序序列中存在而第二个有序序列中不存在的元素。

vector<int> vecIntA;

        vecIntA.push_back(1);

        vecIntA.push_back(3);

        vecIntA.push_back(5);

        vecIntA.push_back(7);

        vecIntA.push_back(9);

 

        vector<int> vecIntB;

        vecIntB.push_back(1);

        vecIntB.push_back(3);

        vecIntB.push_back(5);

        vecIntB.push_back(6);

        vecIntB.push_back(8);

 

        vector<int> vecIntC;

        vecIntC.resize(10);

 

        //并集

        set_union(vecIntA.begin(), vecIntA.end(), vecIntB.begin(), vecIntB.end(), vecIntC.begin());        //vecIntC : {1,3,5,6,7,8,9,0,0,0}

 

        //交集

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

        set_intersection(vecIntA.begin(), vecIntA.end(), vecIntB.begin(), vecIntB.end(), vecIntC.begin());        //vecIntC: {1,3,5,0,0,0,0,0,0,0}

 

        //差集

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

        set_difference(vecIntA.begin(), vecIntA.end(), vecIntB.begin(), vecIntB.end(), vecIntC.begin());            //vecIntC: {7,9,0,0,0,0,0,0,0,0}

8常用的遍历算法

for_each()

  • for_each: 用指定函数依次对指定范围内所有元素进行迭代访问。该函数不得修改序列中的元素。

void show(const int &iItem)

{

    cout << iItem;

}

main()

{

    int iArray[] = {0,1,2,3,4};

    vector<int> vecInt(iArray,iArray+sizeof(iArray)/sizeof(iArray[0]));

for_each(vecInt.begin(), vecInt.end(), show);

 

//结果打印出0 1 2 3 4

}

 

transform()

  • transform: 与for_each类似,遍历所有元素,但可对容器的元素进行修改

    int increase (int i)

    {

        return i+1;

    }

 

main()

        {

            vector<int> vecIntA;

            vecIntA.push_back(1);

            vecIntA.push_back(3);

            vecIntA.push_back(5);

            vecIntA.push_back(7);

            vecIntA.push_back(9);

 

 

            transform(vecIntA.begin(),vecIntA.end(),vecIntA.begin(),increase);        //vecIntA : {2,4,6,8,10}

        }

posted on 2018-05-02 23:20  狂自私  阅读(259)  评论(0编辑  收藏  举报