C++ STL演算法總結

tcfellow發表於2018-01-11

大多過載的演算法都同時有兩個版本的:

  • 用"=="判斷元素相等,或者用"x<y,y<x"比較大小判斷相等
  • 多出一個型別引數"Pred"和函式形參"Pred op",通過判斷表示式op(x,y)的返回值來判斷x==y或者x<y。 比如有兩個版本的min_element:
iterator min_element(iterator first, iterator last);
iterator min_element(iterator first, iterator last,Pred op);
複製程式碼

STL中的演算法大致有以下7種:

需要說明的是,演算法名字並不代表實際意義,可以用自己的想象力做演算法名字之外的事情;同時有些非常用演算法並未列出

1.不變序列演算法

該類演算法不修改演算法所作用的容器或物件

適用於順序容器和關聯容器

時間複雜度都是O(n)

常用演算法:

名稱 說明(程式碼為函式模板,InIt代表迭代器,簡單的不說明)
find InIt find(InIt first, InIt last, const T& val);
count size_t count(InIt first, InIt last, const T& val);
min
max
min_element FwdIt min_element(FwdIt first, FwdIt last);
max_element FwdIt max_element(FwdIt first, FwdIt last);
search 查詢另一區間第一次出現的位置
find_first_of
find_end
equal 判斷兩區間是否相等
for_each Fun for_each(InIt first, InIt last, Fun f);

2.變值演算法

會修改源區間或目標區間元素的值

值被修改的那個區間不可以是關聯容器(關聯容器會涉及到重新排序)

常用演算法:

名稱 說明(Init輸入迭代器,OutIt輸出迭代器)
for_each
copy OutIt copy(InIt first, InIt last, OutIt x);
copy_backward
transform OutIt transform(InIt first, InIt last, OutIt x, Unop uop);
swap_ranges
fill
fill_n
generate
generate_n
replace
replace_if
replace_copy
replace_copy_if

3.刪除演算法

刪除一個容器中的某些元素

刪除演算法不應作用於關聯容器(關聯容器會涉及到元素排序)

演算法複雜度都是o(n)

刪除並不會使元素減少

* 將所有應該被刪除的元素看做空位子
* 用留下的元素從後往前移, 依次去填空位子
* 空位置填滿後,剩下的位置由剛開始的所在位置元素填(即剩下的位置不變)
複製程式碼
名稱 說明
remove 刪除區間中等於某個值的元素
unique 刪除區間中連續相等的元素, 只留下一個(可自定義比較器)
remove_if
remove_copy
remove_copy_if
unique_copy

4.變序演算法

變序演算法改變容器中元素的順序,但是不改變元素的值

變序演算法不適用於關聯容器

演算法複雜度都是O(n)的

名稱 說明(FwdIt迭代器)
reverse 顛倒區間的前後次序
rotate 將區間進行迴圈左移
next_permutation 將區間改為下一個排列(可自定義比較器)
prev_permutation 將區間改為上一個排列(可自定義比較器)
random_shuffle 隨機打亂區間內元素的順序
stable_patition 把區間內滿足某個條件的元素移到前面,不滿足該條件的移到後面,而對這兩部分元素, 分別保持它們原來的先後次序不變
partition 把區間內滿足某個條件的元素移到前面,不滿足該條件的移到後面
rotate_copy 將區間以首尾相接的形式進行旋轉後的結果拷貝到另一個區間,源區間不變
reverse_copy 把一個區間顛倒後的結果拷貝到另一個區間,源區間不變

5.排序演算法

排序演算法需要隨機訪問迭代器的支援

不適用於關聯容器和list

比前面的變序演算法複雜度更高, 一般是O(nlog(n))

名稱 說明(RanIt迭代器)
sort void sort(RanIt first, RanIt last, Pred pr)
stable_sort
partial_sort
partial_sort_copy
nth_element
make_heap
push_heap
pop_heap
sort_heap

sort 實際上是快速排序, 時間複雜度 O(n*log(n))

  • 平均效能最優
  • 但是最壞的情況下, 效能可能非常差

如果要保證 “最壞情況下” 的效能, 那麼可以使用stable_sort

  • stable_sort 實際上是歸併排序, 特點是能保持相等元素之間的先後次序
  • 在有足夠儲存空間的情況下, 複雜度為 n * log(n), 否則複雜度為n * log(n) * log(n)
  • stable_sort 用法和 sort相同。

排序演算法要求隨機存取迭代器的支援, 所以list不能使用排序演算法, 要使用list自帶的sort成員函式list::sort。

6.有序區間演算法

要求所操作的區間是已經從小到大排好序的

需要隨機訪問迭代器的支援

有序區間演算法不能用於關聯容器和list

名稱 說明(前6個很常用)
binary_search 判斷區間中是否包含某個元素(折半查詢)
includes 判斷是否一個區間中的每個元素,都在另一個區間中
lower_bound 查詢最後一個不小於某值的元素的位置
upper_bound 查詢第一個大於某值的元素的位置
equal_range 同時獲取lower_bound和upper_bound
merge 合併兩個有序區間到第三個區間
set_union 將兩個有序區間的並拷貝到第三個區間
set_intersection 將兩個有序區間的交拷貝到第三個區間
set_difference 將兩個有序區間的差拷貝到第三個區間
set_symmetric_difference 將兩個有序區間的對稱差拷貝到第三個區間
inplace_merge 將兩個連續的有序區間原地合併為一個有序區間

bitset

bitset一個實際上不屬於STL演算法,但是會很常用。

template<size_t N>
class bitset{
    ...
}
bitset<40>bst; #bst是一個由40位組成的物件,用bitset的函式可以方便地訪問任何一位
複製程式碼

bitset的成員函式:

bitset<N>& operator&=(const bitset<N>& rhs);
bitset<N>& operator|=(const bitset<N>& rhs);
bitset<N>& operator^=(const bitset<N>& rhs);
bitset<N>& operator<<=(size_t num);
bitset<N>& operator>>=(size_t num);
bitset<N>& set(); //全部設成1
bitset<N>& set(size_t pos, bool val = true); //設定某位
bitset<N>& reset(); //全部設成0
bitset<N>& reset(size_t pos); //某位設成0
bitset<N>& flip(); //全部翻轉
bitset<N>& flip(size_t pos); //翻轉某位 
reference operator[](size_t pos); //返回對某位的引用
bool operator[](size_t pos) const; //判斷某位是否為1
reference at(size_t pos);
bool at(size_t pos) const;
unsigned long to_ulong() const; //轉換成整數
string to_string() const; //轉換成字串
size_t count() const; //計算1的個數
size_t size() const;
bool operator==(const bitset<N>& rhs) const;
bool operator!=(const bitset<N>& rhs) const; 
bool test(size_t pos) const; //測試某位是否為 1
bool any() const; //是否有某位為1
bool none() const; //是否全部為0
bitset<N> operator<<(size_t pos) const;
bitset<N> operator>>(size_t pos) const;
bitset<N> operator~();
static const size_t bitset_size = N;
#注意: 第0位在最右邊
複製程式碼

總結起來呢,就是實現容器或物件元素的查刪改比較排序

相關文章