# C++ algorithm 函式庫 > 作者:王一哲 > 日期:2023年8月24日 ## 前言 C++ algorithm 函式庫中有許多好用的工具,例如排序用的 sort、反轉資料用的 reverse,在 APCS 及 能力競賽中都能使用 algorithm 函式庫,善用這些工具可以少寫很多程式碼。接下來的的程式碼中都省略了以下幾行 ```cpp #include <iostream> #include <algorithm> #include <vector> using namespace std; ``` <br /> ## 不會改變容器中元素的函式 ### all_of 測試範圍中是否所有的元素皆符合條件 語法為 ```cpp all_of(起點位址, 終點位址, 條件); ``` 測試範圍包含起點位址,不包含終點位址,如果**範圍中所有的元素皆符合條件或是範圍中沒有任何元素回傳 1**,如果有**任何一個元素不符合條件回傳 0**。例如以下的程式碼 ```cpp= bool isPositive (int n) { return n > 0; } int main() { vector<int> a = {1, 3, 5, -2, -4, -6}; cout << all_of(a.begin(), a.end(), isPositive) << endl; // 印出 0 cout << all_of(a.begin(), a.end(), [](int x){return x > 0;}) << endl; // 印出 0 vector<int> b = {1, 3, 5, 2, 4, 6}; cout << all_of(b.begin(), b.end(), [](int x){return x > 0;}) << endl; // 印出 1 vector<int> c; cout << all_of(c.begin(), c.end(), [](int x){return x > 0;}) << endl; // 印出 1 return 0; } ``` <br /> ### any_of 測試範圍中是否有任何一個元素符合條件 語法為 ```cpp any_of(起點位址, 終點位址, 條件); ``` 測試範圍包含起點位址,不包含終點位址,如果**範圍中任何一個元素符合條件回傳 1**,如果**所有元素皆不符合條件或是範圍中沒有任何元素回傳 0**。例如以下的程式碼 ```cpp= bool isPositive (int n) { return n > 0; } int main() { vector<int> a = {1, 3, 5, -2, -4, -6}; cout << any_of(a.begin(), a.end(), isPositive) << endl; // 印出 1 cout << any_of(a.begin(), a.end(), [](int x){return x > 0;}) << endl; // 印出 1 vector<int> b = {-1, -3, -5, -2, -4, -6}; cout << any_of(b.begin(), b.end(), [](int x){return x > 0;}) << endl; // 印出 0 vector<int> c; cout << any_of(c.begin(), c.end(), [](int x){return x > 0;}) << endl; // 印出 0 return 0; } ``` <br /> ### none_of 測試範圍中是否沒有任何一個元素符合條件 語法為 ```cpp none_of(起點位址, 終點位址, 條件); ``` 測試範圍包含起點位址,不包含終點位址,如果**範圍中沒有任何一個元素符合條件或是範圍中沒有任何元素回傳 1**,如果**所有元素皆符合條件回傳 0**。例如以下的程式碼 ```cpp= bool isPositive (int n) { return n > 0; } int main() { vector<int> a = {1, 3, 5, -2, -4, -6}; cout << none_of(a.begin(), a.end(), isPositive) << endl; // 印出 0 cout << none_of(a.begin(), a.end(), [](int x){return x > 0;}) << endl; // 印出 0 vector<int> b = {-1, -3, -5, -2, -4, -6}; cout << none_of(b.begin(), b.end(), [](int x){return x > 0;}) << endl; // 印出 1 vector<int> c; cout << none_of(c.begin(), c.end(), [](int x){return x > 0;}) << endl; // 印出 1 return 0; } ``` <br /> ### for_each 套用自訂函式到範圍中的所有元素 語法為 ```cpp for_each(起點位址, 終點位址, 自訂函式); ``` 範圍包含起點位址,不包含終點位址。例如以下的程式碼,編譯後執行會印出 1 3 5 2 4 6。 ```cpp= void myfunc (int n) { cout << n << " "; } int main() { vector<int> a = {1, 3, 5, 2, 4, 6}; for_each(a.begin(), a.end(), myfunc); cout << endl; for_each(a.begin(), a.end(), [](int x){cout << x << " ";}); cout << endl; return 0; } ``` <br /> ### find 於範圍中尋找指定的元素 語法為 ```cpp find(起點位址, 終點位址, 指定的元素); ``` 範圍包含起點位址,不包含終點位址。如果有找到指定的元素,會回傳對應的迭代器,如果範圍中有好幾個指定的元素,只會回傳第一個;如果沒有找到指定的元素,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 1, 2, 1, 2}; auto it = find(a.begin(), a.end(), 2); cout << it - a.begin() << endl; // it - a.begin() 才會是索引值,印出 1 if (find(a.begin(), a.end(), -1) == a.end()) cout << "-1 is not in a." << endl; // -1 不在 a 之中 ``` <br /> ### find_if 於範圍中尋找符合條件的元素 語法為 ```cpp find_if(起點位址, 終點位址, 條件); ``` 範圍包含起點位址,不包含終點位址。如果有找到符合條件的元素,會回傳對應的迭代器,如果範圍中有好幾個符合條件的元素,只會回傳第一個;如果沒有找到符合條件的元素,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= bool isEven (int n) { return n%2 == 0; } int main() { vector<int> a = {1, 3, 5, 2, 4, 6}; auto it = find_if(a.begin(), a.end(), isEven); cout << it - a.begin() << endl; // it - a.begin() 才會是索引值,印出 3 auto it2 = find_if(a.begin(), a.end(), [](int x){return x%2 == 0;}); cout << it2 - a.begin() << endl; // it2 - a.begin() 才會是索引值,印出 3 vector<int> b = {1, 3, 5, 7, 9, 11}; auto it3 = find_if(b.begin(), b.end(), isEven); cout << it3 - b.begin() << endl; // it3 - b.begin() 才會是索引值,印出 6,b 當中所有的元素都是奇數 auto it4 = find_if(b.begin(), b.end(), [](int x){return x%2 == 0;}); cout << it4 - b.begin() << endl; // it4 - b.begin() 才會是索引值,印出 6,b 當中所有的元素都是奇數 return 0; } ``` <br /> ### find_if_not 於範圍中尋找不符合條件的元素 語法為 ```cpp find_if_not(起點位址, 終點位址, 條件); ``` 範圍包含起點位址,不包含終點位址。如果有找到不符合條件的元素,會回傳對應的迭代器,如果範圍中有好幾個不符合條件的元素,只會回傳第一個;如果沒有找到不符合條件的元素,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= bool isEven (int n) { return n%2 == 0; } int main() { vector<int> a = {1, 3, 5, 2, 4, 6}; auto it = find_if_not(a.begin(), a.end(), isEven); cout << it - a.begin() << endl; // it - a.begin() 才會是索引值,印出 0 auto it2 = find_if_not(a.begin(), a.end(), [](int x){return x%2 == 0;}); cout << it2 - a.begin() << endl; // it2 - a.begin() 才會是索引值,印出 0 vector<int> b = {2, 4, 6, 8, 10, 12}; auto it3 = find_if_not(b.begin(), b.end(), isEven); cout << it3 - b.begin() << endl; // it3 - b.begin() 才會是索引值,印出 6,b 當中所有的元素都是偶數 auto it4 = find_if_not(b.begin(), b.end(), [](int x){return x%2 == 0;}); cout << it4 - b.begin() << endl; // it4 - b.begin() 才會是索引值,印出 6,b 當中所有的元素都是偶數 return 0; } ``` <br /> ### find_end 於範圍中尋找最後一個子序列 (subsequence) 語法為 ```cpp find_end(起點位址, 終點位址, 子序列起點位址, 子序列終點位址); ``` 範圍包含起點位址,不包含終點位址。如果有找到子序列,會回傳對應的迭代器,如果範圍中有好幾個子序列,只會回傳最後一個;如果沒有找到子序列,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6, 1, 3, 5, 2, 4, 6}, b = {5, 2, 4}, c = {-1, -2, -3}; auto it = find_end(a.begin(), a.end(), b.begin(), b.end()); cout << it - a.begin() << endl; // it - a.begin() 才會是索引值,印出 8 auto it2 = find_end(a.begin(), a.end(), c.begin(), c.end()); cout << it2 - a.begin() << endl; // it2 - a.begin() 才會是索引值,印出 12 ``` <br /> ### find_first_of 於範圍1中尋找第一個出現的範圍2中任何一個元素 語法為 ```cpp find_first_of(起點位址, 終點位址, 起點位址1, 終點位址2); ``` 範圍包含起點位址,不包含終點位址。如果有找到範圍2中任何一個元素,會回傳對應的迭代器,如果範圍1中有好幾個範圍2中任何一個元素,只會回傳第一個;如果沒有找到範圍2中任何一個元素,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6, 1, 3, 5, 2, 4, 6}, b = {2, 5, 4}, c = {-1, -2, -3}; auto it = find_first_of(a.begin(), a.end(), b.begin(), b.end()); cout << it - a.begin() << endl; // it - a.begin() 才會是索引值,印出 2 auto it2 = find_first_of(a.begin(), a.end(), c.begin(), c.end()); cout << it2 - a.begin() << endl; // it2 - a.begin() 才會是索引值,印出 12 ``` <br /> ### adjancet_find 於範圍中尋找兩個相鄰且相同的元素 語法為 ```cpp adjancet_find(起點位址, 終點位址); ``` 範圍包含起點位址,不包含終點位址。如果有找到兩個相鄰且相同的元素,會回傳第一個元素對應的迭代器,如果範圍中有好幾組兩個相鄰且相同的元素,只會回傳第一組;如果沒有找到兩個相鄰且相同的元素,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 2, 1, 3, 5, 3, 3, 4, 6}; auto it = adjacent_find(a.begin(), a.end()); cout << "a[" << it - a.begin() << "] = " << *it << endl; // 印出 a[3] = 2 auto it2 = adjacent_find(++it, a.end()); cout << "a[" << it2 - a.begin() << "] = " << *it2 << endl; // 印出 a[8] = 3 vector<int> b = {1, 3, 5, 2, 4, 6}; auto it3 = adjacent_find(b.begin(), b.end()); cout << it3 - b.begin() << endl; // 印出 6 ``` <br /> ### count 於範圍中計算指定元素的個數 語法為 ```cpp count(起點位址, 終點位址, 指定的元素); ``` 範圍包含起點位址,不包含終點位址,回傳值格式為 int。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6, 1, 1, 2, 2, 2, 3}; cout << count(a.begin(), a.end(), 1) << endl; // 印出 3 cout << count(a.begin(), a.end(), -1) << endl; // 印出 0 ``` <br /> ### count_if 於範圍中計算符合條件的元素個數 語法為 ```cpp count_if(起點位址, 終點位址, 條件); ``` 範圍包含起點位址,不包含終點位址,回傳值格式為 int。例如以下的程式碼。 ```cpp= bool isEven (int n) { return n%2 == 0; } int main() { vector<int> a = {1, 3, 5, 2, 4, 6, 8}; cout << count_if(a.begin(), a.end(), isEven) << endl; // 印出 4 cout << count_if(a.begin(), a.end(), [](int x){return x%2 == 0;}) << endl; // 印出 4 cout << count_if(a.begin(), a.end(), [](int x){return x < 0;}) << endl; // 印出 0 return 0; } ``` <br /> ### mismatch 於兩組範圍中尋找第一組不相同的元素 語法為 ```cpp mismatch(起點位址, 終點位址, 起點位址2, 終點位址2); ``` 範圍包含起點位址,不包含終點位址,回傳值格式為兩個迭代器的 pair。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6}, b = {1, 2, 5, 2, 3, 6}; auto it = mismatch(a.begin(), a.end(), b.begin(), b.end()); cout << "The first mismatching elements are " << *it.first << " and " << *it.second << endl; // 印出 The first mismatching elements are 3 and 2 it = mismatch(++(it.first), a.end(), ++(it.second), b.end()); cout << "The second mismatching elements are " << *it.first << " and " << *it.second << endl; // 印出 The first mismatching elements are 4 and 3 ``` <br /> ### equal 檢查兩組範圍中的元素內容及順序是否相等 語法為 ```cpp equal(起點位址, 終點位址, 起點位址2, 終點位址2); ``` 範圍包含起點位址,不包含終點位址,回傳值格式為 1 或 0。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6}, b = {2, 4, 6}; cout << equal(a.begin(), a.end(), b.begin(), b.end()) << endl; // 印出 0 cout << equal(a.begin()+3, a.end(), b.begin(), b.end()) << endl; // 印出 1 ``` <br /> ### is_permutation 檢查兩組範圍中的元素內容是否相等 語法為 ```cpp is_permutation(起點位址, 終點位址, 起點位址2, 終點位址2); ``` 範圍包含起點位址,不包含終點位址,回傳值格式為 1 或 0。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6}, b = {2, 6, 4}; cout << is_permutation(a.begin(), a.end(), b.begin(), b.end()) << endl; // 印出 0 cout << is_permutation(a.begin()+3, a.end(), b.begin(), b.end()) << endl; // 印出 1 ``` <br /> ### search 於範圍中尋找第一個子序列 (subsequence) 語法為 ```cpp search(起點位址, 終點位址, 子序列起點位址, 子序列終點位址); ``` 範圍包含起點位址,不包含終點位址。如果有找到子序列,會回傳對應的迭代器,如果範圍中有好幾個子序列,只會回傳第一個;如果沒有找到子序列,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6, 1, 3, 5}, b = {3, 5}, c = {2, 6}; auto it = search(a.begin(), a.end(), b.begin(), b.end()); if (it != a.end()) { cout << "{3, 5} is found in a[" << it - a.begin() << "]" << endl; // 印出 1 } else { cout << "{3, 5} is not found in a." << endl; } auto it2 = search(a.begin(), a.end(), c.begin(), c.end()); if (it2 != a.end()) { cout << "{2, 6} is found in a[" << it2 - a.begin() << "]" << endl; } else { cout << "{2, 6} is not found in a." << endl; // 印出 {2, 6} is not found in a. } ``` <br /> ### search_n 於範圍中尋找連續且指定數量的特定元素 語法為 ```cpp search_n(起點位址, 終點位址, 數量, 特定元素); ``` 範圍包含起點位址,不包含終點位址。如果有找到連續且指定數量的特定元素,會回傳第一個元素對應的迭代器;如果沒有找到連續且指定數量的特定元素,會回傳終點位址對應的迭代器。例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 3, 5, 5, 5, 7, 7, 7, 7}; auto it = search_n(a.begin(), a.end(), 2, 3); if (it != a.end()) { cout << "Two 3s are found in a[" << it - a.begin() << "]" << endl; // 印出 1 } else { cout << "Two 3s are not found in a." << endl; } auto it2 = search_n(a.begin(), a.end(), 4, 5); if (it2 != a.end()) { cout << "Four 5s are found in a[" << it2 - a.begin() << "]" << endl; } else { cout << "Four 5s are not found in a." << endl; // 印出 Four 5s are not found in a. } vector<int> b = {1, 3, 5, 7, 3, 5, 7, 5, 7, 7}; auto it3 = search_n(b.begin(), b.end(), 2, 3); cout << it3 - b.begin() << endl; // 印出 10 ``` <br /> ## 會改變容器中元素的函式 ### copy 複製指定範圍中的元素 語法為 ```cpp copy(起點位址, 終點位址, 存放資料起點位址); ``` 範圍包含起點位址,不包含終點位址。例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); copy(a.begin()+2, a.end()-1, b.begin()); // b 的長度為 6,只複製了 3 個元素 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 3 4 5 0 0 0 vector<int> c (a.begin()+2, a.end()-1); // 也可以在建立 vector 時複製資料 for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 3 4 5 ``` <br /> ### copy_n 複製指定起點位址及數量的元素 語法為 ```cpp copy_n(起點位址, 數量, 存放資料起點位址); ``` 範圍包含起點位址,不包含終點位址,存放資料的容器長度要大於、等於複製資料的數量。例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6), c (6); copy_n(a.begin()+2, 3, b.begin()); for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 3 4 5 0 0 0 copy_n(a.begin(), 6, c.begin()); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 2 3 4 5 6 ``` <br /> ### copy_if 複製範圍中符合條件的元素 語法為 ```cpp copy_if(起點位址, 終點位址, 存放資料起點位址, 條件); ``` 範圍包含起點位址,不包含終點位址,存放資料的容器長度要大於、等於複製資料的數量。例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6), c (6); copy_if(a.begin(), a.end(), b.begin(), [](int x){return x%2 == 0;}); for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 2 4 6 0 0 0 copy_if(a.begin(), a.end(), c.begin(), [](int x){return x%2 == 1;}); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 3 5 0 0 0 ``` <br /> ### copy_backward 複製指定範圍中的元素並從存放資料終點位址向前填入 語法為 ```cpp copy_backward(起點位址, 終點位址, 存放資料終點位址); ``` 範圍包含起點位址,不包含終點位址,存放資料的容器長度要大於、等於複製資料的數量,填入的資料仍然按照原來的順序。例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (8); copy_backward(a.begin(), a.end(), b.end()); for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 0 0 1 2 3 4 5 6 ``` <br /> ### move 移動指定範圍中的元素至存放資料起點位址 語法為 ```cpp move(起點位址, 終點位址, 存放資料起點位址); 存放資料容器名稱 = move(來源資料容器名稱); ``` 範圍包含起點位址,不包含終點位址,存放資料的容器長度要大於、等於複製資料的數量。例如以下的程式碼,在說明書中像是第2行程式碼會清空 a 的內容,但是我測試時 a 仍然保有原來的內容。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); move(a.begin(), a.end(), b.begin()); cout << "a" << endl; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 cout << "b" << endl; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 2 3 4 5 6 b = move(a); cout << "a" << endl; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 沒有印出任何內容 cout << "b" << endl; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 2 3 4 5 6 ``` <br /> ### move_backward 移動指定範圍中的元素並從存放資料終點位址向前填入 語法為 ```cpp move_backward(起點位址, 終點位址, 存放資料終點位址); ``` 範圍包含起點位址,不包含終點位址,存放資料的容器長度要大於、等於複製資料的數量,填入的資料仍然按照原來的順序。例如以下的程式碼,在說明書中像是第2行程式碼會清除 a[1]、a[2]、a[3],但是我測試時 a 仍然保有原來的內容。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); move_backward(a.begin()+1, a.begin()+4, b.end()); cout << "a" << endl; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 cout << "b" << endl; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 0 0 0 2 3 4 ``` <br /> ### swap 交換兩個容器的資料 語法為 ```cpp swap(容器1, 容器2); ``` 例如以下的程式碼。 ```cpp= int a = 1, b = -1; swap(a, b); cout << "a = " << a << ", b = " << b << endl; // 印出 a = -1, b = 1 vector<int> c = {1, 2, 3}, d = {4, 5, 6}; swap(c, d); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 4 5 6 for(auto it = d.begin(); it != d.end(); it++) cout << *it << " \n"[it == d.end()-1]; // 印出 1 2 3 ``` <br /> ### swap_ranges 交換兩個容器中指定範圍的元素 語法為 ```cpp swap_ranges(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b = {6, 5, 4, 3, 2, 1}; swap_ranges(a.begin()+1, a.begin()+4, b.begin()); cout << "a" << endl; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 6 5 4 5 6 cout << "b" << endl; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 2 3 4 3 2 1 ``` <br /> ### iter_swap 交換兩個迭代器對應的元素 語法為 ```cpp iter_swap(迭代器1, 迭代器2); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b = {6, 5, 4, 3, 2, 1}; iter_swap(a.begin()+1, b.begin()+2); cout << "a" << endl; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 4 3 4 5 6 cout << "b" << endl; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 6 5 2 3 2 1 ``` <br /> ### transform 套用函式到容器1的元素,將結果儲存到目標位址 語法為 ```cpp transform(容器1起點位址, 容器1終點位址, 目標起點位址, 函式); transform(容器1起點位址, 容器1終點位址, 容器2起點位址, 目標起點位址, 函式); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); transform(a.begin(), a.end(), b.begin(), [](int x){return ++x;}); cout << "Plus one" << endl; cout << "a: "; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 a: 1 2 3 4 5 6 cout << "b: "; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 b: 2 3 4 5 6 7 transform(a.begin(), a.end(), b.begin(), a.begin(), plus<int>()); cout << "Plus b to a" << endl; cout << "a: "; for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 a: 3 5 7 9 11 13 cout << "b: "; for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 b: 2 3 4 5 6 7 ``` <br /> ### replace 取代範圍中指定的元素 語法為 ```cpp replace(起點位址, 終點位址, 被取代的元素, 新的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 2, 4, 3, 6}; replace(a.begin(), a.end(), 3, -3); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 a: 1 -3 2 4 -3 6 ``` <br /> ### replace_if 取代範圍中符合條件的元素 語法為 ```cpp replace_if(起點位址, 終點位址, 條件, 新的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; replace_if(a.begin(), a.end(), [](int x){return x%2 == 0;}, 0); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 0 3 0 5 0 ``` <br /> ### replace_copy 取代容器1中符合條件的元素並儲存到容器2 語法為 ```cpp replace_copy(容器1起點位址, 容器1終點位址, 容器2起點位址, 被取代的元素, 新的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 2, 4, 3, 6}, b (6); replace_copy(a.begin(), a.end(), b.begin(), 3, -3); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 3 2 4 3 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 -3 2 4 -3 6 ``` <br /> ### replace_copy_if 複製容器1的元素,取代其中符合條件的元素,再儲存到容器2 語法為 ```cpp replace_copy_if(容器1起點位址, 容器1終點位址, 容器2起點位址, 條件, 新的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); replace_copy_if(a.begin(), a.end(), b.begin(), [](int x){return x%2 == 0;}, 0); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 0 3 0 5 0 ``` <br /> ### fill 於指定範圍內填入元素 語法為 ```cpp fill(起點位址, 終點位址, 填入的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a (6); fill(a.begin()+1, a.begin()+4, -1); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 0 -1 -1 -1 0 0 ``` <br /> ### fill_n 於指定起點開始填入指定數量的元素 語法為 ```cpp fill_n(起點位址, 數量, 填入的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a (6); fill_n(a.begin()+1, 3, -1); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 0 -1 -1 -1 0 0 ``` <br /> ### generate 於指定範圍填入代入自訂函式産生的元素 語法為 ```cpp generate(起點位址, 終點位址, 自訂函式); ``` 例如以下的程式碼。 ```cpp= #include <iostream> #include <algorithm> #include <vector> #include <ctime> #include <cstdlib> using namespace std; int main() { srand(time(NULL)); vector<int> a (6); generate(a.begin(), a.end(), [](){return rand()%10;}); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 隨機印出 6 個 0 ~ 9 的整數 return 0; } ``` <br /> ### generate_n 於指定起點位址開始填入指定數量、代入自訂函式産生的元素 語法為 ```cpp generate_n(起點位址, 數量, 自訂函式); ``` 例如以下的程式碼。 ```cpp= #include <iostream> #include <algorithm> #include <vector> #include <ctime> #include <cstdlib> using namespace std; int main() { srand(time(NULL)); vector<int> a (6); generate_n(a.begin(), 6, [](){return rand()%10;}); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 隨機印出 6 個 0 ~ 9 的整數 return 0; } ``` <br /> ### remove 移除範圍中指定的元素 語法為 ```cpp remove(起點位址, 終點位址, 要移除的元素); ``` 回傳值為範圍中沒有被移除的元素終點位址,例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 2, 4, 3, 6}; auto itEnd = remove(a.begin(), a.end(), 3); for(auto it = a.begin(); it != itEnd; it++) cout << *it << " \n"[it == itEnd-1]; // 印出 1 2 4 6 ``` <br /> ### remove_if 移除範圍中符合條件的元素 語法為 ```cpp remove_if(起點位址, 終點位址, 條件); ``` 回傳值為範圍中沒有被移除的元素終點位址,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; auto itEnd = remove_if(a.begin(), a.end(), [](int x){return x%2 == 0;}); for(auto it = a.begin(); it != itEnd; it++) cout << *it << " \n"[it == itEnd-1]; // 印出 1 3 5 ``` <br /> ### remove_copy 移除容器1中指定元素後將剩下的元素填入容器2 語法為 ```cpp remove_copy(容器1起點位址, 容器1終點位址, 容器2起點位址, 要移除的元素); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 2, 4, 3, 6}, b (6); remove_copy(a.begin(), a.end(), b.begin(), 3); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 3 2 4 3 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 2 4 6 0 0 ``` <br /> ### remove_copy_if 移除容器1中符合條件的元素後將剩下的元素填入容器2 語法為 ```cpp remove_copy_if(容器1起點位址, 容器1終點位址, 容器2起點位址, 條件); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); remove_copy_if(a.begin(), a.end(), b.begin(), [](int x){return x%2 == 0;}); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 3 5 0 0 0 ``` <br /> ### remove_copy_if 移除容器1中符合條件的元素後將剩下的元素填入容器2 語法為 ```cpp remove_copy_if(容器1起點位址, 容器1終點位址, 容器2起點位址, 條件); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); remove_copy_if(a.begin(), a.end(), b.begin(), [](int x){return x%2 == 0;}); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 3 5 0 0 0 ``` <br /> ### unique 如果範圍中有連續出現的元素,只留下第一個 語法為 ```cpp unique(起點位址, 終點位址); ``` 回傳值為留下的資料終點位址,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 2, 3, 3, 2}; auto itEnd = unique(a.begin(), a.end()); a.resize(itEnd - a.begin()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 2 ``` <br /> ### unique_copy 如果範圍中有連續出現的元素,只留下第一個,將留下的元素複製到另一個容器 語法為 ```cpp unique_copy(容器1起點位址, 容器1終點位址, 容器2起點位址); ``` 回傳值為容器2填入資料的終點位址,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 2, 3, 3, 2}, b (6); auto itEnd = unique_copy(a.begin(), a.end(), b.begin()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 2 3 3 2 b.resize(itEnd - b.begin()); for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 2 3 2 ``` <br /> ### reverse 將範圍中的元素前後反轉 語法為 ```cpp reverse(起點位址, 終點位址); ``` 沒有回傳值,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; reverse(a.begin(), a.end()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 6 5 4 3 2 1 ``` <br /> ### reverse_copy 將範圍中的元素前後反轉再複製到容器2 語法為 ```cpp reverse_copy(容器1起點位址, 容器1終點位址, 容器2起點位址); ``` 不會改變容器1的內容。例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); reverse_copy(a.begin(), a.end(), b.begin()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 6 5 4 3 2 1 ``` <br /> ### rotate 將範圍中的元素向前平移,最前面的元素移到最後面 語法為 ```cpp rotate(起點位址, 新的起點位址, 終點位址); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; rotate(a.begin(), a.begin()+3, a.end()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 4 5 6 1 2 3 ``` <br /> ### rotate_copy 將範圍中的元素向前平移,最前面的元素移到最後面,再複製到容器2 語法為 ```cpp rotate_copy(起點位址, 新的起點位址, 終點位址, 容器2起點位址); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (6); rotate_copy(a.begin(), a.begin()+3, a.end(), b.begin()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 4 5 6 1 2 3 ``` <br /> ### random_shuffle 隨機排列範圍中的元素 語法為 ```cpp random_shuffle(起點位址, 終點位址); ``` 可以使用內建的 rand 函式,並搭配 srant(time(NULL)),例如以下的程式碼。 ```cpp= #include <iostream> #include <algorithm> #include <vector> #include <ctime> #include <cstdlib> using namespace std; int main() { srand(time(NULL)); vector<int> a = {1, 2, 3, 4, 5, 6}; random_shuffle(a.begin(), a.end()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 1 ~ 6 隨機排列 return 0; } ``` <br /> ### shuffle 隨機排列範圍中的元素 語法為 ```cpp shuffle(起點位址, 終點位址, default_random_engine(seed)); ``` 使用 random 函式庫的 default_random_engine 函式,並搭配 chrono 函式庫的工具産生亂數種子,例如以下的程式碼。 ```cpp= #include <iostream> #include <algorithm> #include <vector> #include <random> #include <chrono> using namespace std; int main() { unsigned int seed = chrono::system_clock::now().time_since_epoch().count(); vector<int> a = {1, 2, 3, 4, 5, 6}; shuffle(a.begin(), a.end(), default_random_engine(seed)); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 1 ~ 6 隨機排列 return 0; } ``` <br /> ## 操作分區 ### is_partitioned 檢查範圍中所有元素是否符合條件 語法為 ```cpp is_partitioned(起點位址, 終點位址, 條件); ``` 如果所有元素都符合條件回傳 1,如果有任何一個元素不符合條件回傳0,例如以下的程式碼。 ```cpp= vector<int> a = {0, 2, 4, 5, 6, 8}, b = {0, 2, 4, 6, 8, 10}; cout << is_partitioned(a.begin(), a.end(), [](int x){return x%2 == 0;}) << endl; // 印出 0 cout << is_partitioned(b.begin(), b.end(), [](int x){return x%2 == 0;}) << endl; // 印出 1 ``` <br /> ### partition 依照條件將範圍分區 語法為 ```cpp partition(起點位址, 終點位址, 條件); ``` 回傳值為分區位址對應的迭代器,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; auto bound = partition(a.begin(), a.end(), [](int x){return x%2 == 0;}); for(auto it = a.begin(); it != bound; it++) cout << *it << " "; // 印出 6 2 4 cout << endl; for(auto it = bound; it != a.end(); it++) cout << *it << " "; // 印出 3 5 1 cout << endl; ``` <br /> ### stable_partition 依照條件將範圍分區並排序 語法為 ```cpp stable_partition(起點位址, 終點位址, 條件); ``` 回傳值為分區位址對應的迭代器,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; auto bound = stable_partition(a.begin(), a.end(), [](int x){return x%2 == 0;}); for(auto it = a.begin(); it != bound; it++) cout << *it << " "; // 印出 2 4 6 cout << endl; for(auto it = bound; it != a.end(); it++) cout << *it << " "; // 印出 1 3 5 cout << endl; ``` <br /> ### partition_copy 依照條件將範圍分區並存入另外兩個容器 語法為 ```cpp partition_copy(起點位址, 終點位址, 容器2起點位址, 容器3起點位址, 條件); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b (3), c(3); partition_copy(a.begin(), a.end(), b.begin(), c.begin(), [](int x){return x%2 == 0;}); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 2 4 6 for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 3 5 ``` <br /> ### partition_point 回傳依照條件將範圍分區的位址 語法為 ```cpp partition_point(起點位址, 終點位址, 條件); ``` 回傳值為分區位址對應的迭代器,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b; partition(a.begin(), a.end(), [](int x){return x%2 == 0;}); auto bound = partition_point(a.begin(), a.end(), [](int x){return x%2 == 0;}); b.assign(a.begin(), bound); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 6 2 4 3 5 1 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 6 2 4 ``` <br /> ## 排序 ### sort 排序範圍內的元素 語法為 ```cpp sort(起點位址, 終點位址, 比較式); ``` 比較式預設值為由小到大排序,也可以引用內建函式 greater 由大到小排序,或是依照自訂函式排序,例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 2, 4, 6}; sort(a.begin(), a.end()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 6 sort(a.begin(), a.end(), greater<>()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 6 5 4 3 2 1 ``` <br /> ### stable_sort 排序範圍內的元素,如果元素相等時保持原來的順序 語法為 ```cpp stable_sort(起點位址, 終點位址, 比較式); ``` 例如以下的程式碼。 ```cpp= vector<float> a = {2.5, 2.1, 2.3, 1.5, 1.1, 1.3}; stable_sort(a.begin(), a.end(), [](float x, float y){return int(x) < int(y);}); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1.5 1.1 1.3 2.5 2.1 2.3 ``` <br /> ### partial_sort 排序範圍內部分的元素 語法為 ```cpp partial_sort(起點位址, 中點位址, 終點位址, 比較式); ``` 比較式預設值為由小到大排序,如果採用預設值,中點位址前會放入整個範圍中由小到大排序的元素,再由中點位址開始放入剩下的元素,如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10}; partial_sort(a.begin(), a.begin()+5, a.end()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 2 3 4 5 9 7 6 8 10 ``` <br /> ### partial_sort_copy 排序容器1中指定範圍的元素並複製到容器2 語法為 ```cpp partial_sort_copy(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址, 比較式); ``` 比較式預設值為由小到大排序,不會改變容器1的內容,例如以下的程式碼。 ```cpp= vector<int> a = {1, 10, 2, 9, 3, 8, 4, 7, 5, 6}, b(5); partial_sort_copy(a.begin(), a.begin()+5, b.begin(), b.end()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 10 2 9 3 8 4 7 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 1 2 3 9 10 partial_sort_copy(a.begin(), a.begin()+5, b.begin(), b.end(), greater<>()); for(auto it = a.begin(); it != a.end(); it++) cout << *it << " \n"[it == a.end()-1]; // 印出 1 10 2 9 3 8 4 7 5 6 for(auto it = b.begin(); it != b.end(); it++) cout << *it << " \n"[it == b.end()-1]; // 印出 10 9 3 2 1 ``` <br /> ### is_sorted 檢查範圍中的元素是否已排序 語法為 ```cpp is_sorted(起點位址, 終點位址, 比較式); ``` 比較式預設值為由小到大排序,如果已排序回傳 1,如果未排序回傳 0,例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 6, 4, 2}; cout << is_sorted(a.begin(), a.end()) << endl; // 印出 0 cout << is_sorted(a.begin(), a.begin()+3) << endl; // 印出 1 cout << is_sorted(a.begin()+3, a.end(), greater<>()) << endl; // 印出 1 sort(a.begin(), a.end()); cout << is_sorted(a.begin(), a.end()) << endl; // 印出 1 ``` <br /> ### is_sorted_until 找出範圍中第一個未由小到大排序的元素位址 語法為 ```cpp is_sorted_until(起點位址, 終點位址); ``` 如果所有元素都已經由小到大排序,回傳終點位址,例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 6, 4, 2}; auto it = is_sorted_until(a.begin(), a.end()); cout << it - a.begin() << endl; // 印出 4 sort(a.begin(), a.end()); auto it2 = is_sorted_until(a.begin(), a.end()); cout << it2 - a.begin() << endl; // 印出 6 ``` <br /> ## 二分搜尋 這些函式只能用在已經全部或部分排序的資料。 <br /> ### lower_bound、upper_bound、equal_range 找出範圍中指定元素的位址 語法為 ```cpp lower_bound(起點位址, 終點位址, 元素); upper_bound(起點位址, 終點位址, 元素); equal_range(起點位址, 終點位址, 元素); ``` lower_bound 回傳值為指定元素左側的位址,upper_bound 回傳值為指定元素右側的位址,equal_range 回傳值格式為 pair,同時包含 lower_bound 及 upper_bound,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; auto it = lower_bound(a.begin(), a.end(), 3); cout << it - a.begin() << endl; // 印出 2 auto it2 = upper_bound(a.begin(), a.end(), 3); cout << it2 - a.begin() << endl; // 印出 3 auto bounds = equal_range(a.begin(), a.end(), 3); cout << "lower_bound: " << bounds.first - a.begin() << " upper_bound: " << bounds.second - a.begin() << endl; // 印出 lower_bound: 2 upper_bound: 3 ``` <br /> ### binary_search 用二分搜尋法檢查範圍中是否有指定元素 語法為 ```cpp binary_search(起點位址, 終點位址, 元素); ``` 如果找到指定元素回傳 1,如果沒有找到指定元素回傳 0,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}; cout << binary_search(a.begin(), a.end(), 3) << endl; // 印出 1 cout << binary_search(a.begin(), a.end(), -3) << endl; // 印出 0 ``` <br /> ## 處理已排序的資料 ### merge 合併兩組已排序的資料並存入另一個容器 語法為 ```cpp merge(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址, 容器3起點位址); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 5, 7, 9}, b = {2, 4, 6, 8, 10}, c (10); merge(a.begin(), a.end(), b.begin(), b.end(), c.begin()); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 2 3 4 5 6 7 8 9 10 ``` <br /> ### includes 檢查容器1是否包含容器2的資料且順序相同 語法為 ```cpp includes(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址); ``` 如果是回傳 1,反之回傳 0,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5, 6}, b = {2, 3, 4}, c = {4, 3, 2}; cout << includes(a.begin(), a.end(), b.begin(), b.end()) << endl; // 印出 1 cout << includes(a.begin(), a.end(), c.begin(), c.end()) << endl; // 印出 0 ``` <br /> ### set_union 將容器1、2的元素組合成聯集存入容器3 語法為 ```cpp set_union(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址, 容器3起點位址); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 3, 5, 5}, b = {2, 2, 4, 6, 6}, c (15); auto itEnd = set_union(a.begin(), a.end(), b.begin(), b.end(), c.begin()); c.resize(itEnd - c.begin()); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 2 2 3 3 4 5 5 6 6 ``` <br /> ### set_intersection 將容器1、2的元素組合成交集存入容器3 語法為 ```cpp set_intersection(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址, 容器3起點位址); ``` 例如以下的程式碼。 ```cpp= vector<int> a = {1, 3, 3, 5, 5}, b = {1, 2, 3, 4, 5}, c (15); auto itEnd = set_intersection(a.begin(), a.end(), b.begin(), b.end(), c.begin()); c.resize(itEnd - c.begin()); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 3 5 ``` <br /> ### set_difference 將容器1、2的元素組合成差集存入容器3 語法為 ```cpp set_difference(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址, 容器3起點位址); ``` 將容器1的元素刪除容器2中也有的元素,剩下的元素存入容器3,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5}, b = {1, 3, 3, 5, 5}, c (15); auto itEnd = set_difference(a.begin(), a.end(), b.begin(), b.end(), c.begin()); c.resize(itEnd - c.begin()); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 2 4 ``` <br /> ### set_symmetric_difference 將容器1、2的元素組合成對稱差集存入容器3 語法為 ```cpp set_symmetric_difference(容器1起點位址, 容器1終點位址, 容器2起點位址, 容器2終點位址, 容器3起點位址); ``` 對稱差是將聯集扣掉交集,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5}, b = {2, 4, 6, 8, 10}, c (15); auto itEnd = set_symmetric_difference(a.begin(), a.end(), b.begin(), b.end(), c.begin()); c.resize(itEnd - c.begin()); for(auto it = c.begin(); it != c.end(); it++) cout << *it << " \n"[it == c.end()-1]; // 印出 1 3 5 6 8 10 ``` <br /> ## 最大值、最小值 ### min 回傳最小值、max 回傳最大值、minmax 同時回傳最小值及最大值 語法為 ```cpp min({元素1, 元素2, 元素3, ...}); max({元素1, 元素2, 元素3, ...}); minmax({元素1, 元素2, 元素3, ...}); ``` 例如以下的程式碼。 ```cpp= cout << "min = " << min({1, 2, 3, 4, 5}) << endl; // 印出 min = 1 cout << "max = " << max({1, 2, 3, 4, 5}) << endl; // 印出 max = 5 auto result = minmax({1, 2, 3, 4, 5}); cout << "min = " << result.first << ", max = " << result.second << endl; // 印出 min = 1, max = 5 ``` <br /> ### min_element 回傳範圍中的最小值、max_element 回傳範圍中的最大值、minmax_element 同時回傳範圍中的最小值及最大值 語法為 ```cpp min_element({元素1, 元素2, 元素3, ...}); max_element({元素1, 元素2, 元素3, ...}); minmax_element({元素1, 元素2, 元素3, ...}); ``` min_element 及 max_element 回傳值為對應的迭代器,minmax_element 回傳值為迭代器的 pari,例如以下的程式碼。 ```cpp= vector<int> a = {1, 2, 3, 4, 5}; auto it1 = min_element(a.begin(), a.end()); cout << "The min element of a is a[" << it1 - a.begin() << "] = " << *it1 << endl; // 印出 The min element of a is a[0] = 1 auto it2 = max_element(a.begin(), a.end()); cout << "The max element of a is a[" << it2 - a.begin() << "] = " << *it2 << endl; // 印出 The max element of a is a[4] = 5 auto result = minmax_element(a.begin(), a.end()); cout << "min(a) = " << *(result.first) << ", max(a) = " << *(result.second) << endl; // 印出 min(a) = 1, max(a) = 5 ``` <br /> ## 結語 以上是 algorithm 函式庫大部分的函式,其中我最常用到的函式為 sort、reverse、find、count、min、max,尤其是 sort,在競賽及檢定中經常用到,如果不使用 sort 就要當場寫氣泡排序或是快速排序,會浪費不少時間。 <br /> ## 參考資料 [cplusplus.com algorithm](https://cplusplus.com/reference/algorithm/) --- ####### tags:`C++`