C++?STL?常用算法操作實(shí)例詳解
C++ 標(biāo)準(zhǔn)模板庫(kù)(STL)提供了豐富的算法庫(kù)(定義在 <algorithm> 頭文件中),這些算法多為通用函數(shù)模板,可配合容器和迭代器高效操作數(shù)據(jù)。
1、非修改序列算法
這些算法不會(huì)改變它們所操作的容器中的元素。
1.1 find 和 find_if
find(begin, end, value):查找第一個(gè)等于value的元素,返回迭代器(未找到返回end)。find_if(begin, end, predicate):查找第一個(gè)滿足謂詞的元素。find_end(begin, end, sub_begin, sub_end):查找子序列最后一次出現(xiàn)的位置。
vector<int> nums = {1, 3, 5, 7, 9};
// 查找值為5的元素
auto it = find(nums.begin(), nums.end(), 5);
if (it != nums.end()) {
cout << "found: " << *it << endl; // 輸出:5
}
// 查找第一個(gè)大于6的元素
auto it2 = find_if(nums.begin(), nums.end(), [](int x) {
return x > 6;
});
cout << "first >6: " << *it2 << endl; // 輸出:7
// 查找子序列
vector<int> sub = {3, 5};
auto it3 = find_end(nums.begin(), nums.end(), sub.begin(), sub.end());
if (it3 != nums.end()) {
cout << "subsequence starts at index: " << it3 - nums.begin() << endl; // 輸出:1
}1.2 count 和 count_if
count(begin, end, value):統(tǒng)計(jì)等于value的元素個(gè)數(shù)。count_if(begin, end, predicate):統(tǒng)計(jì)滿足謂詞(predicate)的元素個(gè)數(shù)。
std::vector<int> vec = {1, 2, 3, 2, 4, 2};
int cnt = std::count(vec.begin(), vec.end(), 2); // 計(jì)數(shù)2的個(gè)數(shù),結(jié)果為3
int even_cnt = std::count_if(vec.begin(), vec.end(), [](int x) {
return x % 2 == 0;
}); // 偶數(shù)個(gè)數(shù),結(jié)果為41.3 for_each
對(duì)范圍內(nèi)的每個(gè)元素應(yīng)用一個(gè)函數(shù)
std::vector<int> vec = {1, 2, 3, 4, 5};
std::for_each(vec.begin(), vec.end(), [](int& x) {
x *= 2; // 將每個(gè)元素乘以2
});
// 現(xiàn)在vec變?yōu)閧2, 4, 6, 8, 10}1.4 equal 與 mismatch
equal(b1, e1, b2):判斷兩個(gè)范圍[b1,e1)和[b2, b2+(e1-b1))是否相等。mismatch(b1, e1, b2):返回兩個(gè)范圍中第一個(gè)不相等元素的迭代器對(duì)(pair)。
vector<int> a = {1, 2, 3};
vector<int> b = {1, 2, 4};
vector<int> c = {1, 2, 3, 4};
// 比較a和b的前3個(gè)元素
bool is_equal = equal(a.begin(), a.end(), b.begin());
cout << "a == b? " << boolalpha << is_equal << endl; // 輸出:false
// 查找a和c的第一個(gè)不匹配元素
auto mis = mismatch(a.begin(), a.end(), c.begin());
if (mis.first != a.end()) {
cout << "mismatch: " << *mis.first << " vs " << *mis.second << endl; // 無(wú)輸出(a和c前3元素相等)
}1.5 all_of, any_of, none_of
檢查范圍內(nèi)元素是否全部、存在或沒(méi)有滿足條件的
std::vector<int> vec = {2, 4, 6, 8};
bool all_even = std::all_of(vec.begin(), vec.end(), [](int x) {
return x % 2 == 0;
}); // true
bool any_odd = std::any_of(vec.begin(), vec.end(), [](int x) {
return x % 2 != 0;
}); // false
bool none_negative = std::none_of(vec.begin(), vec.end(), [](int x) {
return x < 0;
}); // true2、修改序列算法
這些算法會(huì)修改它們所操作的容器中的元素。
2.1 copy 和 copy_if
copy(begin, end, dest):將[begin, end)中的元素復(fù)制到dest開(kāi)始的位置。copy_if(begin, end, dest, predicate):復(fù)制滿足謂詞的元素到dest。
vector<int> src = {1, 2, 3, 4, 5};
vector<int> dest(5); // 需預(yù)先分配足夠空間
// 復(fù)制所有元素
copy(src.begin(), src.end(), dest.begin()); // dest: [1,2,3,4,5]
// 復(fù)制偶數(shù)元素到新容器
vector<int> evens;
copy_if(src.begin(), src.end(), back_inserter(evens), [](int x) {
return x % 2 == 0;
}); // evens: [2,4]注意:back_inserter(dest) 會(huì)自動(dòng)調(diào)用 push_back,無(wú)需提前分配空間。
2.2 transform
對(duì)范圍內(nèi)的每個(gè)元素應(yīng)用一個(gè)函數(shù),并將結(jié)果存儲(chǔ)在另一個(gè)范圍內(nèi)
vector<int> nums = {1, 2, 3};
vector<int> squares(3);
// 計(jì)算平方(單參數(shù)轉(zhuǎn)換)
transform(nums.begin(), nums.end(), squares.begin(), [](int x) {
return x * x;
}); // squares: [1,4,9]
// 兩容器元素相加(雙參數(shù)轉(zhuǎn)換)
vector<int> a = {1, 2, 3};
vector<int> b = {4, 5, 6};
vector<int> sum(3);
transform(a.begin(), a.end(), b.begin(), sum.begin(), [](int x, int y) {
return x + y;
}); // sum: [5,7,9]2.3 replace、replace_if與 replace_copy
replace(begin, end, old_val, new_val):將所有old_val替換為new_val。replace_if(begin, end, predicate, new_val):替換滿足謂詞的元素。replace_copy(begin, end, dest, old_val, new_val):復(fù)制時(shí)替換元素(不修改原容器)。
vector<int> nums = {1, 2, 3, 2, 5};
// 替換所有2為20
replace(nums.begin(), nums.end(), 2, 20); // nums: [1,20,3,20,5]
// 替換大于10的元素為0
replace_if(nums.begin(), nums.end(), [](int x) {
return x > 10;
}, 0); // nums: [1,0,3,0,5]
// 復(fù)制時(shí)替換3為300(原容器不變)
vector<int> res;
replace_copy(nums.begin(), nums.end(), back_inserter(res), 3, 300); // res: [1,0,300,0,5]2.4 remove、remove_if 與 erase
remove(begin, end, value):將等于value的元素 “移動(dòng)” 到容器末尾,返回新的邏輯尾迭代器(不實(shí)際刪除元素,需配合erase)。remove_if(begin, end, predicate):移動(dòng)滿足謂詞的元素到末尾。
vector<int> nums = {1, 2, 3, 2, 4};
// 邏輯刪除所有2(移動(dòng)到末尾)
auto new_end = remove(nums.begin(), nums.end(), 2); // nums: [1,3,4,2,2]
// 物理刪除(真正移除元素)
nums.erase(new_end, nums.end()); // nums: [1,3,4]
// 結(jié)合lambda刪除偶數(shù)
nums = {1, 2, 3, 4, 5};
nums.erase(remove_if(nums.begin(), nums.end(), [](int x) {
return x % 2 == 0;
}), nums.end()); // nums: [1,3,5]2.5 unique
移除范圍內(nèi)連續(xù)的重復(fù)元素,返回新的邏輯結(jié)尾迭代器。通常與erase結(jié)合使用。
std::vector<int> vec = {1, 1, 2, 2, 3, 3, 3, 4, 5};
auto last = std::unique(vec.begin(), vec.end());
vec.erase(last, vec.end()); // vec變?yōu)閧1, 2, 3, 4, 5}2.6 reverse
反轉(zhuǎn)范圍內(nèi)的元素順序
std::vector<int> vec = {1, 2, 3, 4, 5};
std::reverse(vec.begin(), vec.end()); // vec變?yōu)閧5, 4, 3, 2, 1}2.7 rotate
旋轉(zhuǎn)范圍內(nèi)的元素,使中間元素成為新的第一個(gè)元素
std::vector<int> vec = {1, 2, 3, 4, 5};
std::rotate(vec.begin(), vec.begin() + 2, vec.end()); // 以3為起點(diǎn)旋轉(zhuǎn),vec變?yōu)閧3, 4, 5, 1, 2}2.8 shuffle
隨機(jī)重排范圍內(nèi)的元素(需要C++11或更高版本)
#include <random>
#include <algorithm>
std::vector<int> vec = {1, 2, 3, 4, 5};
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(vec.begin(), vec.end(), g); // 隨機(jī)打亂vec中的元素3、排序和相關(guān)算法
3.1 sort、stable_sort 與 partial_sort
sort(begin, end):對(duì)元素進(jìn)行快速排序(不穩(wěn)定,平均時(shí)間復(fù)雜度 O (n log n))。stable_sort(begin, end):穩(wěn)定排序(相等元素相對(duì)位置不變)。partial_sort(begin, mid, end):部分排序,使[begin, mid)為整個(gè)范圍中最小的元素并排序。
std::vector<int> vec = {5, 3, 1, 4, 2};
std::sort(vec.begin(), vec.end()); // 默認(rèn)升序,vec變?yōu)閧1, 2, 3, 4, 5}
std::sort(vec.begin(), vec.end(), std::greater<int>()); // 降序,vec變?yōu)閧5, 4, 3, 2, 1}
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a < b;
}); // 升序,自定義比較
std::vector<std::pair<int, int>> vec = {{1, 2}, {2, 1}, {1, 1}, {2, 2}};
std::stable_sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) {
return a.first < b.first; // 按first排序,保持相等元素的相對(duì)順序
});
std::vector<int> vec = {5, 3, 1, 4, 2, 6};
// 將最小的3個(gè)元素放在前面并排序
std::partial_sort(vec.begin(), vec.begin() + 3, vec.end());
// 現(xiàn)在vec前三個(gè)元素是1, 2, 3,后面是未排序的4, 5, 63.2 nth_element
重新排列范圍,使得指定位置的元素等于排序后的元素,并且左邊的元素都不大于它,右邊的元素都不小于它
std::vector<int> vec = {5, 3, 1, 4, 2, 6};
// 找到第三小的元素(索引2)
std::nth_element(vec.begin(), vec.begin() + 2, vec.end());
// 現(xiàn)在vec[2]是3,它左邊的元素<=3,右邊的>=33.3 binary_search、lower_bound、upper_bound
需在已排序的容器上使用
binary_search(begin, end, value):判斷value是否存在(返回bool)。lower_bound(begin, end, value):返回第一個(gè)不小于value的元素迭代器。upper_bound(begin, end, value):返回第一個(gè)大于value的元素迭代器。
vector<int> sorted = {1, 3, 3, 5, 7}; // 必須先排序
// 判斷3是否存在
bool exists = binary_search(sorted.begin(), sorted.end(), 3); // true
// 查找第一個(gè)>=3的元素
auto lb = lower_bound(sorted.begin(), sorted.end(), 3);
cout << "lower_bound index: " << lb - sorted.begin() << endl; // 輸出:1
// 查找第一個(gè)>3的元素
auto ub = upper_bound(sorted.begin(), sorted.end(), 3);
cout << "upper_bound index: " << ub - sorted.begin() << endl; // 輸出:33.4 merge
合并兩個(gè)已排序的范圍到新容器(保持排序)
vector<int> a = {1, 3, 5};
vector<int> b = {2, 4, 6};
vector<int> merged(a.size() + b.size());
// 合并a和b(均需已排序)
merge(a.begin(), a.end(), b.begin(), b.end(), merged.begin()); // merged: [1,2,3,4,5,6]4、堆算法
STL提供了將范圍作為堆來(lái)操作的算法,包括make_heap, push_heap, pop_heap, sort_heap等。
std::vector<int> vec = {4, 1, 3, 2, 5};
std::make_heap(vec.begin(), vec.end()); // 構(gòu)建最大堆,vec變?yōu)閧5, 4, 3, 2, 1}
vec.push_back(6);
std::push_heap(vec.begin(), vec.end()); // 將新元素加入堆,vec變?yōu)閧6, 4, 5, 2, 1, 3}
std::pop_heap(vec.begin(), vec.end()); // 將最大元素移到末尾,vec變?yōu)閧5, 4, 3, 2, 1, 6}
int max_val = vec.back(); // 獲取最大元素6
vec.pop_back(); // 移除最大元素
std::sort_heap(vec.begin(), vec.end()); // 將堆排序?yàn)樯蛐蛄?,vec變?yōu)閧1, 2, 3, 4, 5}5、最小/最大值算法
5.1 min 和 max
返回兩個(gè)值或初始化列表中的最小/最大值
int a = 5, b = 3;
int min_val = std::min(a, b); // 3
int max_val = std::max(a, b); // 5
auto min_of_list = std::min({4, 2, 8, 5, 1}); // 1
auto max_of_list = std::max({4, 2, 8, 5, 1}); // 85.2 min_element 和 max_element
返回范圍內(nèi)的最小/最大元素的迭代器
std::vector<int> vec = {3, 1, 4, 2, 5};
auto min_it = std::min_element(vec.begin(), vec.end()); // 指向1
auto max_it = std::max_element(vec.begin(), vec.end()); // 指向55.3 minmax_element (C++11)
同時(shí)返回范圍內(nèi)的最小和最大元素的迭代器
std::vector<int> vec = {3, 1, 4, 2, 5};
auto minmax = std::minmax_element(vec.begin(), vec.end());
// minmax.first指向1,minmax.second指向56、數(shù)值算法(在<numeric>中)
6.1 accumulate
計(jì)算范圍內(nèi)元素的累加和(或自定義操作)
#include <numeric>
std::vector<int> vec = {1, 2, 3, 4, 5};
int sum = std::accumulate(vec.begin(), vec.end(), 0); // 和,初始值為0,結(jié)果為15
int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>()); // 乘積,初始值為1,結(jié)果為1206.2 inner_product
計(jì)算兩個(gè)范圍的內(nèi)積(或自定義操作)
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {4, 5, 6};
int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0); // 1*4 + 2*5 + 3*6 = 326.3 iota
用連續(xù)遞增的值填充范圍
std::vector<int> vec(5); std::iota(vec.begin(), vec.end(), 10); // 填充為10, 11, 12, 13, 14
6.4 partial_sum
計(jì)算部分和,將結(jié)果存儲(chǔ)在目標(biāo)范圍內(nèi)
std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst(src.size());
std::partial_sum(src.begin(), src.end(), dst.begin()); // dst變?yōu)閧1, 3, 6, 10, 15}6.5 adjacent_difference
計(jì)算相鄰元素的差值,將結(jié)果存儲(chǔ)在目標(biāo)范圍內(nèi)
std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst(src.size());
std::adjacent_difference(src.begin(), src.end(), dst.begin()); // dst變?yōu)閧1, 1, 1, 1, 1}7、其他
7.1 generate
用生成函數(shù)填充范圍
std::vector<int> vec(5);
int n = 0;
std::generate(vec.begin(), vec.end(), [&n]() {
return n++;
}); // 填充為0, 1, 2, 3, 47.2 generate_n
用生成函數(shù)填充范圍的開(kāi)始n個(gè)元素
std::vector<int> vec(5);
int n = 10;
std::generate_n(vec.begin(), 3, [&n]() {
return n++;
}); // 前三個(gè)元素為10, 11, 12,后兩個(gè)保持不變7.3 includes
檢查一個(gè)排序范圍是否包含另一個(gè)排序范圍的所有元素
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = {2, 4};
bool includes = std::includes(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()); // true7.3 set_union, set_intersection, set_difference, set_symmetric_difference
執(zhí)行集合操作:并集、交集、差集和對(duì)稱差集
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = {3, 4, 5, 6, 7};
std::vector<int> result;
// 并集
std::set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result));
// result為{1, 2, 3, 4, 5, 6, 7}
// 交集
result.clear();
std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result));
// result為{3, 4, 5}
// 差集 (v1 - v2)
result.clear();
std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result));
// result為{1, 2}
// 對(duì)稱差集 (v1 ∪ v2 - v1 ∩ v2)
result.clear();
std::set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result));
// result為{1, 2, 6, 7}8、常見(jiàn)問(wèn)題
sort與stable_sort的區(qū)別?sort采用快速排序(實(shí)際是 introsort 算法),不穩(wěn)定(相等元素的相對(duì)位置可能改變),平均時(shí)間復(fù)雜度 O (n log n)。stable_sort采用歸并排序,穩(wěn)定(相等元素相對(duì)位置不變),時(shí)間復(fù)雜度 O (n log n),但空間開(kāi)銷略大。
- 為什么
remove算法需要配合erase使用?remove算法的原理是 “覆蓋” 要?jiǎng)h除的元素,將保留的元素移到前面,返回新的邏輯尾迭代器,但不修改容器的實(shí)際大小。erase則通過(guò)迭代器范圍真正刪除元素,修改容器大小。因此需結(jié)合使用:container.erase(remove(...), container.end())。
- 哪些算法需要容器是已排序的?
- 二分查找系列(
binary_search、lower_bound、upper_bound)、集合算法(set_intersection、set_union等)、merge等,這些算法依賴有序性實(shí)現(xiàn)高效操作(如二分查找 O (log n))。
- 二分查找系列(
到此這篇關(guān)于C++ STL 常用算法的文章就介紹到這了,更多相關(guān)C++ STL 算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt?加載?libjpeg?庫(kù)出現(xiàn)“長(zhǎng)跳轉(zhuǎn)已經(jīng)運(yùn)行”錯(cuò)誤問(wèn)題解決
這篇文章主要介紹了Qt?加載?libjpeg?庫(kù)出現(xiàn)“長(zhǎng)跳轉(zhuǎn)已經(jīng)運(yùn)行”錯(cuò)誤,本文給大家分享完美解決方案,需要的朋友可以參考下2023-04-04
C語(yǔ)言實(shí)現(xiàn)餐飲結(jié)賬管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)餐飲結(jié)賬管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11
使用c++實(shí)現(xiàn)OpenCV繪制圓端矩形
這篇文章主要介紹了使用c++實(shí)現(xiàn)OpenCV繪制圓端矩形,其中著重的講解了OpenCV使用過(guò)程中需要注意的一些小細(xì)節(jié),避免浪費(fèi)大家在開(kāi)發(fā)過(guò)程中浪費(fèi)多余的時(shí)間2021-08-08
C語(yǔ)言實(shí)現(xiàn)三子棋游戲簡(jiǎn)易版
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)三子棋游戲簡(jiǎn)易版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07

