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}

        }


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: