《C++Primer》算法概覽 C++ 算法概覽

C++ 算法概覽

  1. beg和end表示元素範圍的迭代器
  2. beg2表示第二個序列開始位置迭代器,end2表示第二個序列末尾迭代器(如果有的話)。如沒有end2則假定系列2至少與beg和end表示的範圍一樣大。beg和beg2類型不必匹配,但必須保證兩個序列中的元素可以執行特性操作或調用給定的可調用對象。
  3. des表示目的序列的迭代器。對於給定輸入序列,算法需要生成多少元素,目的序列保證有足夠的空間存放算法生成的元素。
  4. unaryPred和binaryPred是一元和二元謂詞,分別接受來自輸入序列的元素,兩個謂詞都返回可用作條件的類型。
  5. comp是一個二元謂詞,滿足關聯容器中對關鍵字序的要求
  6. unaryOp和binaryOp是可調用對象,分別使用來自輸入序列的一個和兩個實參來調用。

查找對象的算法

這些算法在一個輸入序列中搜索一個指定值或者一個值的序列。每個算法都有兩個重載的版本,一個使用底層類型的==來比較;另一個使用用戶給定的unaryPred和binaryPred比較。

1. 簡單查找算法

find(beg, end, val);                 // 返回迭代器,指向第一個等於val的元素。未找到,返回end
find_if(beg, end, unaryPred);        // 返回迭代器,指向第一個滿足unaryPred的元素。未找到,end
find_if_not(beg, end, unaryPred);    // 指向第一個不滿足unaryPred的元素, 未找到,返回end
count(beg, end, val);                // 返回一個計數器,指出val出現了多少次
count_if(beg, end, unaryPred);       // 統計有多少個元素滿足unaryPred
all_of(beg, end, unaryPred);
any_of(beg, end, unaryPred);
none_of(beg, end, unaryPred);
// 上面幾個都返回bool值,分別判斷是否所有元素滿足unaryPred、任一元素滿足unaryPred、所有元素都不滿足unaryPred。
// 如序列爲空,any_of返回false,all_of和none_of返回true

2. 查找重複值算法

下面算法要求前向迭代器,因爲有binaryPred了,需要前後兩個元素比較,要多遍掃描。

// 返回指向第一對相鄰重複元素的迭代器。如不存在,返回end
adjacent_find(beg, end);
adjacent_find(beg, end, binaryPred);

// 返回一個迭代器,從此位置開始有count個連續相等元素。如不存在返回end
search_n(beg, end, count, val)
search_n(beg, end, count, val, binaryPred)

3. 查找子序列算法

除了find_first_of之外,都要求兩個前向迭代器;find_first_of第一個只需要輸入迭代器,第二個序列需要前向迭代器,因爲需要支持多次掃描。

// 返回第二個序列在第一個序列中第一次出現的位置。如未找到,返回end1
search(beg1, end1, beg2, end2)
search(beg1, end1, beg2, end2, binaryPred)

// 返回第一個序列中迭代器,指向序列二中任意一個元素在序列一中首次出現的位置。如未找到,則返回end1
find_first_of(beg1, end1, beg2, end2)
find_first_of(beg1, end1, beg2, end2, binaryPred)

// 類似search,返回最後一次出現的位置。如未找到則返回end1
find_end(beg1, end1, beg2, end2)
find_end(beg1, end1, beg2, end2, binaryPred)

其他只讀算法

要求前兩個實參都是輸入迭代器,同樣提供兩個版本,一個用底層類型的==,一個用用戶指定的unaryPred或binaryPred比較元素。

// 對輸入序列中的每個元素應用可調用對象unaryOp,忽略返回值。迭代器支持的話則可以修改元素。
for_each(beg, end, unaryOp):

// 比較兩個序列中的元素,返回一個pair,表示兩個序列中第一個不匹配的元素,若均匹配,則pair的first成員爲end1,second成員是指向beg2中偏移量等於第一個序列長度的位置。
mismatch(beg1, end1, beg2)
mismatch(beg1, end1, beg2, binaryPred)

// 確定兩個序列是否相等。相等返回true,不相等返回false。
equal(beg1, end1, beg2)
equal(beg1, end1, beg2, binaryPred)

二分搜索算法

  • 這些算法要求至少前向迭代器,如果提供隨機訪問迭代器,性能會好很多。無論什麼迭代器都執行對數次比較操作,但是前向迭代器必須花費線性次數的迭代器操作來移動到序列中要比較的元素位置。
  • 另外這些算法要求序列已經是有序的,它們的行爲類似關聯容器中的同名成員。equal_range、lower_bound和upper_bound算法返回迭代器,指向給定序列中的正確插入位置——插入後還能保持有序。如果給定元素比序列中所有元素都大,則返回尾後迭代器。
  • 每個算法提供兩個版本,一個用元素類型的<來檢測,令一個使用給定的比較操作(比如comp(x, y))來檢測。
// 返回一個迭代器,表示第一個小於等於val的元素, 如果不存在這樣的元素則返回end
lower_bound(beg, end, val)
lower_bound(beg, end, val, comp)

// 返回一個迭代器,表示第一個大於等於val的元素, 如果不存在這樣的元素則返回end
upper_bound(beg, end, val)
upper_bound(beg, end, val, comp)

// 返回一個pair, first成員爲lower_bound返回的迭代器,second成員爲upper_bound返回的迭代器
equal_bound(beg, end, val)
equal_bound(beg, end, val, comp)

// 返回一個bool值,指出序列中是否含有指定值val。對於兩個值x和y, 當x不小於y且y也不小於x時認爲它們相等。
binary_search(beg, end, val)
binary_search(beg, end, val, comp)

寫容器元素的算法

1. 只寫不讀元素的算法

這些算法要求一個輸出迭代器,表示目的位置。_n結尾的版本表示第二個參數是寫入的元素個數。

// 給輸入序列的每個元素賦予一個新值。fill將值賦予元素(對於不可拷貝的類型不能用fill),generate執行生成器對象Gen()生成新值。
// fill和generate都返回void, _n結尾的版本返回一個迭代器, 指向寫入到輸出序列的最後一個元素之後的位置
fill(beg, end, val)
fill_n(dest, cnt, val)
generate(beg, end, Gen)
generate_n(dest, cnt, Gen)

2. 使用輸入迭代器的寫算法

這些算法讀取一個輸入序列,將值寫入到一個輸出序列中。它們要求一個名爲dest的輸出迭代器,而表示輸入範圍的迭代器必須是輸入迭代器。

// 從輸入範圍將元素拷貝到dest指定的目的序列。copy拷貝所有元素, copy_if拷貝滿足unaryPred的元素,_n拷貝前n個,輸入序列至少有n個。
copy(beg, end, dest)
copy_if(beg, end, dest, unaryPred)
copy_n(beg, n, dest)

// 對輸入序列中的每個元素調用std::move,將其移動到迭代器dest開始的序列,沒有if和n的版本
move(beg, end, dest)

// 調用給定操作,將結果寫入dest。第一個版本對輸入範圍中的每個元素應用一元操作,第二個版本對兩個輸入序列中元素應用二元操作。
transform(beg, end, dest, unaryOp)
transform(beg, end, beg2, dest, binaryOp)

// 將每個元素拷貝到dest。將指定的元素替換爲new_val。第一個版本替換那些==old_val的元素。第二個版本替換那些滿足unaryPred的元素。
replace_copy(beg, end, dest, old_val, new_val)
replace_copy_if(beg, end, dest, unaryPred, new_val)

// 兩個輸入序列都必須有序,將合併後的序列寫入dest中。第一個版本使用<,第二個版本使用給定的操作。
merge(beg1, end1, beg2, end2, dest)
merge(beg1, end1, beg2, end2, dest, comp):

3. 使用前向迭代器的寫算法

這些算法要求前向迭代器,由於它們是向輸入序列寫入元素,迭代器必須具有寫入元素的權限。

// 交換iter1和iter2所表示的元素,或者將輸入範圍中所有元素與beg2開始的第二個序列中所有元素進行交換。兩個範圍不能有重疊。iter_swap返回void,swap_ranges返回遞增後的beg2,指向最後一個交換元素之後的位置。
iter_swap(iter1, iter2)
swap_ranges(beg1, end1, beg2):

// 用new_val替換每個匹配元素。第一個版本使用==,第二個版本使用一元謂語unaryPred。
replace(beg, end, old_val, new_val)
replace(beg, end, unaryPred, new_val)

4. 使用雙向迭代器的寫算法

這些算法需要在序列中有反向移動的能力,因此它們要求雙向迭代器。

// 從輸入範圍中拷貝或移動元素到指定目的位置。與其他算法不同,dest是輸出序列的尾後迭代器。輸入範圍中的尾元素被拷貝或移動到目的序列的尾元素,然後是倒數第二個元素被移動/拷貝,依此類推。元素在目的序列中的順序與輸入序列中相同。如果範圍爲空,則返回值爲dest;否則返回值表示從*beg中拷貝或移動的元素。
copy_backward(beg, end, dest)
move_backward(beg, end, dest)

// 將同一序列的兩個有序子序列合併爲單一有序序列。beg到mid間的子序列和mid到end之間的子序列被合併。第一個版本使用<,第二個版本使用給定的比較操作,返回void。
inplace_merge(beg, mid, end)
inplace_merge(beg, mid, end, comp)

劃分與排序算法

每個排序和劃分算法都提供了穩定和不穩定版本。穩定版本保證保持相等元素的相對順序。由於穩定算法會做更多的工作,可能比不穩定版本慢得多並消耗更多內存。

1. 劃分算法

一個劃分算法將輸入範圍中的元素劃分爲兩組。第一組包含那些滿足給定謂詞的元素,第二組則包含不滿足給定謂詞的與元素。

// 如果所有滿足謂詞unaryPred的元素都在不滿足unaryPred的元素之前則返回true(序列爲空也返回true),否則返回flase
is_partitioned(beg, end, unaryPred)

// 將滿足unaryPred的元素拷貝到dest1,將不滿足unaryPred的元素拷貝到dest2。返回一個迭代器pair,其first成員表示拷貝到dest1的元素的末尾,其second表示拷貝到dest2的元素的末尾。輸入序列與兩個目的序列都不能重疊
partition_copy(beg, end, dest1, dest2, unaryPred)

// 輸入序列必須是用unaryPred劃分過的。返回滿足unaryPred的範圍的尾後迭代器。如果返回的迭代器不是end,則它指向的元素及其後的元素必須都不滿足unaryPred。
partition_point(beg, end, unaryPred)

// 使用unaryPred劃分輸入序列,滿足unaryPred的元素放在序列開始,不滿足unaryPred的元素放在序列尾部,返回一個迭代器,指向最後一個滿足unaryPred的元素之後的元素,若所有元素均不滿足unaryPred則返回beg。
stable_partition(beg, end, unaryPred)
partition(beg, end, unaryPred)

2. 排序算法

這些算法要求隨機訪問迭代器。每個排序算法都提供兩個重載的版本。一個版本用元素的<運算符來比較元素,另一個版本接受一個額外參數來指定排序關係。partial_sort_copy返回一個指向目的位置的迭代器,其他排序算法都返回void。partial_sort和nth_element只進行部分排序,速度比整體排序算法更快。

// 排序整個範圍
sort(beg, end)
stable_sort(beg, end)
sort(beg, end, comp)
stable_sort(beg, end, comp)

// 返回一個bool值,指出整個輸入序列是否有序
is_sorted(beg, end)
is_sorted(beg, end, comp)

// 在輸入序列中查找最長初始有序子序列,返回子序列尾後迭代器
is_sorted_until(beg, end)
is_sorted_until(beg, end, comp)

// 排序mid-beg個元素。即如果mid-beg=42,則此函數將值最小的42個元素有序放在序列前42個位置。當partial_sort完成後,從beg到mid之間的範圍中的元素已經排好序。已排序返回中的元素都不會比mid後的元素更大。未排序區域中的元素順序是未指定的。
partial_sort(beg, mid, end)
partial_sort(beg, mid, end, comp)

// 排序輸入範圍內的元素,並將足夠多的元素拷貝到destBeg和destEnd所指示的序列中。如果目的序列大於等於輸入範圍則排序整個輸入序列並存入從destBeg開始的輸出序列。若目的序列小於輸入範圍,則拷貝輸入序列中與目的範圍一樣多的元素。算法返回一個迭代器,指向目的序列中已排序部分的尾後迭代器。如果目的序列的大小小於或者等於輸入範圍,則返回destEnd。
partial_sort_copy(beg, end, destBeg, destEnd)
partial_sort_copy(beg, end, destBeg, destEnd, comp)

// 參數nth必須是一個迭代器,指向輸入序列中的一個元素。執行nth_element後,此迭代器指向的元素恰好是整個序列排好序後此位置上的值。序列中的元素會圍繞nth進行劃分: nth之前的元素都小於等於它,而之後的元素都大於等於它。
nth_element(beg, nth, end)
nth_element(beg, nth, end, comp)

6 通用重排操作

這些算法重排輸入序列中元素的順序。前兩個算法remove和unique會重排序列,使得排在序列第一部分的元素滿足某種標準 。它們返回一個迭代器,標記子序列的末尾。其他算法,比如reverse、rotate和random_shuffle都重排整個序列。

這些算法的基本版本都進行“原址”操作,即在輸入序列自身內部重排與元素。三個重排算法提供“拷貝”版本,這些_copy版本完成相同的重排工作,但將重排後的元素寫入到一個指定目的序列中,而不是改變輸入序列。這些算法要求輸出迭代器來表示目的序列。

6.1 使用前向迭代器的重排序列

// 從序列中刪除元素,採用的辦法是用保留的元素覆蓋要刪除的元素。被刪除的是那些==val或者滿足unaryPred的元素。算法返回一個迭代器,指向最後一個保留元素的尾後位置。
remove(beg, end, val)
remove_if(beg, end, unaryPred)
remove_copy(beg, end, dest, val)
remove_copy_if(beg, end, dest, unaryPred)

// 重排序列,對於相鄰的重複元素,通過覆蓋來進行刪除,返回一個迭代器,指向不重複元素的尾後位置。
unique(beg, end)
unique(beg, end, binaryPred)
unique_copy(beg, end, dest)
unique_copy(beg, end, dest, binaryPred)

// 圍繞mid指向的元素進行元素轉動。元素mid成爲首元素,隨後是mid+1到end之前的元素,再接着是beg到mid之前的元素。返回一個迭代器,指向原來beg位置的元素
rotate(beg, mid, end)
rotate_copy(beg, mid, end, dest)

6.2 使用雙向迭代器的重排算法

// 翻轉序列中的元素。reverse返回void,reverse_copy返回一個迭代器,指向拷貝到目的序列的元素的尾後位置。
reverse(beg, end)
reverse_copy(beg, end, dest)

6.3 使用隨機訪問迭代器的重排算法

由於這些算法要隨機重排元素,它們要求隨機訪問迭代器。

// 混洗輸入序列中的元素。第二個版本接受一個可調用對象參數,該對象必須接受一個正整數數值,並生成0到此值的包含區間內的一個服從均勻分佈的隨機整數。shuffle的第三個參數必須滿足均勻分佈隨機數生成器的要求。所有版本都返回void。
random_shuffle(beg, end)
random_shuffle(beg, end, rand)
shuffle(beg, end, Uniform_rand)

7 排列算法

排序算法生成序列的字典序排列。對於一個給定序列,這些算法通過重排它的一個排列來生成字典序中下一個或前一個排列。算法返回一個bool值,指出是否還有下一個或者前一個排列。

這些算法假定序列中的元素都是唯一的,即沒有兩個元素的值是一樣的。另外爲了生成排列,必須既向前又向後處理序列,因此算法要求雙向迭代器。

// 如果第二個序列的某個排列和第一個序列具有相同數目的元素,且元素都相等,則返回true。第一個版本用==比較元素,第二個版本用給定的binaryPred。
is_permutation(beg1, end1, beg2)
is_permutation(beg1, end1, beg2, binaryPred)

// 如果序列已經是最後一個排序,則本函數將序列重排爲最小的序列,並返回false。否則將輸入序列轉爲字典序的下一個排列,返回true。
next_permutation(beg, end)
next_permutation(beg, end, comp)

// 若序列已經是第一個排序,則本函數將序列重排爲最大的序列,返回false。否則將序列轉爲字典序的上一個排序,返回true。
prev_permutation(beg, end)
prev_permutation(beg, end, comp)

8 有序序列的集合算法

集合算法實現了有序序列上的一般集合操作。這些算法與標準庫set容器不同,不要與set上的操作相混淆。這些算法提供了普通順序容器比如vector和list等的類集合行爲。

每種算法都有重載版本,第一個使用元素類型的<運算符,第二個使用給定的比較曹組偶。

// 如果第二個序列中的每個元素都包含在輸入序列中則返回true(這裏使用的是==),否則返回false。
includes(beg, end, beg2, end2)
includes(beg, end, beg2, end2, comp)

// 對兩個序列中的所有元素,創建它們的有序序列,兩個序列都包含的元素在輸出序列中只出現一次。輸出序列保存在dest中。
set_union(beg1, end1, beg2, end2, dest)
set_union(beg1, end1, beg2, end2, dest, comp)

// 對兩個輸入序列中均包含的元素創建它們的有序序列,輸出交集。輸出序列保存在dest中。
set_intersection(beg1, end1, beg2, end2, dest)
set_intersection(beg1, end1, beg2, end2, dest, comp)

// 對出現在第一個序列但不出現在第二個序列中的元素創建一個有序序列。
set_difference(beg1, end1, beg2, end2, dest)
set_difference(beg1, end1, beg2, end2, dest, comp)

// 對只出現在一個序列中的元素,創建一個有序序列。
set_symmetric_difference(beg1, end1, beg2, end2, dest)
set_symmetric_difference(beg1, end1, beg2, end2, dest, comp)

9 最大值和最小值

這些算法使用元素的<運算符或者給定的比較操作。第一組算法對值而非序列進行操作,第二組算法接受一個序列,它們要求輸入迭代器。

// 返回val1和val2中最小值/最大值,或initializer_list中最小值/最大值。兩個實參類型必須完全一致,參數和返回類型都是const引用,意味着對象不會被拷貝。
min(val1, val2)
min(val1, val2, comp)
min(init_list)
min(init_list, comp)
max(val1, val2)
max(val1, val2, comp)
max(init_list)
max(init_list, comp)

// 返回一個pair,分別表示最小值和最大值。
minmax(val1, val2)
minmax(val1, val2, comp)
minmax(init_list)
minmax(init_list, comp)

// min_element和max_element返回指向指向輸入序列中最小和最大元素的迭代器。minmax_element返回一個pair,其first成員爲最小元素,second成員爲最大元素。
min_element(beg, end)
min_element(beg, end, comp)
max_element(beg, end)
max_element(beg, end, comp)
minmax_element(beg, end)
minmax_element(beg, end, comp)

字典序比較:此算法比較兩個序列,根據第一對不相等的元素的相對大小來返回結果。算法使用元素的<運算符或者給定的比較操作。兩個序列都要求用輸入迭代器給出。

// 如果第一個序列在字典序中小於第二個序列,則返回true,否則返回false。如果一個序列比另一個短,且所有元素都與較長序列的對應元素相等,則較短序列在字典序中更小。如果序列長度相同,且對應元素都相等,則再字典序中任何一個都不大於另一個。
lexicographical_compare(beg1, end1, beg2, end2)
lexicographical_compare(beg1, end1, beg2, end2, comp)

10 數值算法

數值算法定義在頭文件numeric中,這些算法要求輸入迭代器,如果算法輸出數據,則使用輸出迭代器表示目的位置。

// 返回輸入序列所有值的和。和的初始值由init指定。返回類型和init的類型相同。第一個版本使用+,第二個版本使用binaryOp。
accumulate(beg, end, init)
accumulate(beg, end, init, binaryOp)

// 返回兩個序列的內積(即對應元素的積的和)。和的初始值由init指定,返回類型和init相同。第一個版本使用* +,第二個版本使用binOp1,binOp2。
inner_product(beg1, end1, beg2, init)  
inner_product(beg1, end1, beg2, init, binOp1, binOp2)

// 將新序列寫入dest,每個新元素的值都等於輸入範圍中當前位置和之前位置上所有元素之和。第一個版本使用+,第二個版本使用binaryOp。
partial_sum(beg, end, dest)
partial_sum(beg, end, dest, binaryOp)

// 將新序列寫入dest,每個新元素(除了首元素)的值都爲輸入範圍中當前位置和前一個位置元素之差。第一個版本使用-,第二個版本使用binaryOp。v
adjacent_difference(beg, end, dest)
adjacent_difference(beg, end, dest, binaryOp)

// 將val賦予首元素,並將遞增後的值賦予下一元素,直至結束。val可以是一個字面值常量。
iota(beg, end, val)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章