--- ###### tags: `2020 師大附中校隊培訓` --- # iterator 與 STL 常用函數 ## 2020 師大附中校隊培訓 #### joylintp #### 10.26.2020 --- ## iterator 迭代器 ---- ### pointer & iterator ```cpp= int arr[] = {9, 4, 8, 7}; int *p = arr; cout << *p << ' ' << *(p + 1) << '\n'; // 9 4 vector<int> v = {9, 4, 8, 7}; vector<int>::iterator i = v.begin(); cout << *i << ' ' << *(i + 1) << '\n'; // 9 4 ``` ---- ### 各種 STL 的 iterator `list` / `set` / `multiset` / `map`:只能往前/後一個元素 `deque` / `vector`:可指定元素位置 ---- ### 各種 STL 的 iterator (cont.) ```cpp= set<int> st; st.insert(5), st.insert(9), st.insert(4), st.insert(8), st.insert(7); set<int>::iterator si = st.begin(); cout << *si << '\n'; // 4 si++, cout << *si << '\n'; // 5 si++, cout << *si << '\n'; // 7 si--, cout << *si << '\n'; // 5 ``` ```cpp= vector<int> v = {5, 9, 4, 8, 7}; vector<int>::iterator vi = v.begin(); cout << *vi << '\n'; // 5 vi++, cout << *vi << '\n'; // 9 vi += 2, cout << *vi << '\n'; // 8 vi -= 3, cout << *vi << '\n'; // 5 ``` ---- ### `next` / `prev` 回傳當前迭代器的下一個/前一個位置 ```cpp= set<int> st; st.insert(5), st.insert(9), st.insert(4), st.insert(8), st.insert(7); set<int>::iterator si = st.begin(); auto sj = si; si++, cout << *si << '\n'; // 5 sj = next(sj), cout << *sj << '\n'; // 5 si--, cout << *si << '\n'; // 4 sj = prev(sj), cout << *sj << '\n'; // 4 ``` ```cpp= vector<int> v = {5, 9, 4, 8, 7}; vector<int>::iterator vi = v.begin(); auto vj = vi; vi++, cout << *vi << '\n'; // 9 vj = next(vj), cout << *vj << '\n'; // 9 vi--, cout << *vi << '\n'; // 5 vj = prev(vj), cout << *vj << '\n'; // 5 ``` ---- ### 常用 iterator #### `v.begin()` `v` 中第一個元素的位置 #### `v.end()` `v` 中最後一個元素後面的位置,對此位置取值會是未知值 對於可指定元素的 STL,此位置即為 `v.begin() + v.size()` #### `v.rbegin()` `v` 中最後一個元素的位置,此為 `reverse_iterator`, 此位置的值與 `prev(v.end())` 相同 --- ## 其他常用函式 ---- ### `swap` 交換兩個型態相同的變數的值 ```cpp= int a = 5, b = 4; swap(a, b); vector<int> va = {5, 4}, vb = {8, 7}; swap(va, vb); swap(va[0], vb[0]); ``` ---- ### `sort` 將 STL 中元素排序,預設為遞減排序,亦可自行設定比較函式 若多元素權重相同則順序可能改變 時間複雜度 $O(n\ log(n))$ ```cpp= bool cmp(int a, int b) { return a % 2 < b % 2; } // ... vector<int> v = {5, 9, 4, 8, 7}; sort(v.begin() + 1, v.begin() + 4); // 5 4 8 9 7 sort(v.begin(), v.end()); // 4 5 7 8 9 sort(v.begin(), v.end(), greater<int>()); // 9 8 7 5 4 sort(v.begin(), v.end(), cmp); // 4 8 7 9 5 ``` ---- ### `stable_sort` 將 STL 中元素排序,預設為遞減排序,亦可自行設定比較函式 若多元素權重相同則在原始順序較前面者仍會在前面 若有額外空間則時間複雜度為 $O(n\ log(n))$;否則為 $O(n\ log^2(n))$ ```cpp= bool cmp(int a, int b) { return a % 2 < b % 2; } // ... vector<int> v = {5, 9, 4, 8, 7}; stable_sort(v.begin(), v.end(), cmp); // 4 8 5 9 7 ``` ---- ### `reverse` 將 STL 中元素前後反轉 時間複雜度 $O(n)$ ```cpp= vector<int> v = {5, 9, 4, 8, 7}; reverse(v.begin() + 1, v.begin() + 4); // 5 8 4 9 7 reverse(v.begin(), v.end()); // 7 9 4 8 5 ``` ---- ### `rotate` `rotate(a, a + i, b)` 向左旋轉 `[a, b)` 之間的元素, 使得原本的第 `a + i` 個元素變為原本第 `a` 個元素的位置 時間複雜度 $O(n)$ ```cpp= vector<int> v = {5, 9, 4, 8, 7}; rotate(v.begin() + 1, v.begin() + 2, v.begin() + 4); // 5 4 8 9 7 rotate(v.begin(), v.begin() + 2, v.end()); // 8 9 7 5 4 ``` ---- ### `prev_permutation` / `next_permutation` 將 STL 中的元素重新排成前一個/後一個字典序 若已是第一個/最後一個字典序會回傳 `false`;否則回傳 `true` 時間複雜度 $O(n)$ ```cpp= vector<int> v = {1, 2, 3}; do { for (int i : v) cout << i << ' '; cout << '\n'; } while (next_permutation(v.begin(), v.end())); // 1 2 3 // 1 3 2 // 2 1 3 // 2 3 1 // 3 1 2 // 3 2 1 ``` ---- ### `random_shuffle` 打亂 STL 中的元素 時間複雜度 $O(n)$ ```cpp= vector<int> v = {5, 9, 4, 8, 7}; random_shuffle(v.begin(), v.begin() + 3); // 4 9 5 8 7 random_shuffle(v.begin(), v.end()); // 8 4 7 5 9 ``` ---- ## `upper_bound` / `loewr_bound` 對於已排序的 STL 容器, `upper_bound` 回傳第一個嚴格大於指定值的元素迭代器 `lower_bound` 回傳第一個大於或等於指定值的元素迭代器 ---- `deque` / `vector` 等 STL 應使用 `lower_bound(v.begin(), v.end(), x)` `set` / `multiset` / `map` 等 STL 應使用 `st.lower_bound(x)` 時間複雜度 $log(n)$ 若 `set` 等 STL 使用了第一種方式, 時間複雜度可能退化成 $O(n)$ ---- ```cpp= vector<int> v = {5, 7}; for (int i = 4; i <= 8; i++) { auto p1 = lower_bound(v.begin(), v.end(), i); auto p2 = upper_bound(v.begin(), v.end(), i); cout << *p1 << ' ' << *p2 << '\n'; } // i == 4: 5 5 // i == 5: 5 7 // i == 6: 7 7 // i == 7: 7 ? // i == 8: ? ? ``` ---- ```cpp= set<int> st; st.insert(5), st.insert(7); for (int i = 4; i <= 8; i++) { auto p1 = st.lower_bound(i); auto p2 = st.upper_bound(i); cout << *p1 << ' ' << *p2 << '\n'; } // i == 4: 5 5 // i == 5: 5 7 // i == 6: 7 7 // i == 7: 7 ? // i == 8: ? ? ```
{"metaMigratedAt":"2023-06-15T14:44:46.949Z","metaMigratedFrom":"Content","title":"iterator 與 STL 常用函數","breaks":true,"contributors":"[{\"id\":\"6b95215f-91a7-4eaf-bcfe-d43740108f96\",\"add\":5763,\"del\":1237}]"}
    319 views