C++ algorithm基操
序列修改
transform
功能:大小寫轉換
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first,UnaryOperation unary_op );
引數:
first1
,last1
- 要變換的第一元素範圍d_first
- 目標範圍的起始,可以等於first1
或first2
unary_op
- 將要應用的一元算符函式。
PS:記得::tolower
::
, 而且是::tolower
,不是::tolower()
#include <iostream> #include <algorithm> using namespace std; string s; int main() { cout<<"請輸入一個含大寫的字串:"; string str; cin>>str; ///轉小寫 transform(str.begin(),str.end(),str.begin(),::tolower); cout<<"轉化為小寫後為:"<<str<<endl; transform(str.begin(),str.end(),str.begin(),::toupper); cout<<"轉化為大寫後為:"<<str<<endl; return 0; }
swap
功能:交換值
void swap( T& a, T& b );
引數:
a
,b
- 要交換的值
#include <algorithm> #include <iostream> int main() { int a = 5, b = 3; // 前 std::cout << a << ' ' << b << '\n'; std::swap(a,b); // 後 std::cout << a << ' ' << b << '\n'; }
swap_ranges
功能:在範圍 [first1, last1)
和始於 first2
的另一範圍間交換元素。
引數
first1
,last1
- 要交換的第一個元素範圍first2
- 要交換的第二個元素範圍的起始
返回值
指向始於 first2
的範圍中被交換的最末元素後一元素的迭代器。
示例
演示來自不同容器的子範圍交換
#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
std::list<int> l = {-1, -2, -3, -4, -5};
std::swap_ranges(v.begin(), v.begin()+3, l.begin());
for(int n : v)
std::cout << n << ' ';
std::cout << '\n';
for(int n : l)
std::cout << n << ' ';
std::cout << '\n';
}
iter_swap
定義
template< class ForwardIt1, class ForwardIt2 >
void iter_swap( ForwardIt1 a, ForwardIt2 b );
引數
a
,b
- 指向要交換的元素的迭代器
示例
下面是選擇排序在 C++ 中的實現
#include <random>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
template<class ForwardIt>
void selection_sort(ForwardIt begin, ForwardIt end)
{
for (ForwardIt i = begin; i != end; ++i)
std::iter_swap(i, std::min_element(i, end));
}
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(-10, 10);
std::vector<int> v;
std::generate_n(back_inserter(v), 20, bind(dist, gen));
std::cout << "Before sort: ";
for(auto e : v) std::cout << e << " ";
selection_sort(v.begin(), v.end());
std::cout << "\nAfter sort: ";
for(auto e : v) std::cout << e << " ";
std::cout << '\n';
}
reverse
定義
template< class BidirIt >
void reverse( BidirIt first, BidirIt last );
功能
反轉 [first, last)
範圍中的元素順序
引數
first
,last
- 要反轉的元素的範圍
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<int> v{1,2,3};
std::reverse(std::begin(v), std::end(v));
for(auto e : v) std::cout << e;
std::cout << '\n';
int a[] = {4, 5, 6, 7};
std::reverse(std::begin(a), std::end(a));
for(auto e : a) std::cout << e;
}
reverse_copy
定義
template< class BidirIt, class OutputIt >
OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first );
功能
複製來自範圍 [first, last)
的元素到始於 d_first
的新範圍,使得新範圍中元素以逆序排列。
引數
first
,last
- 要複製的元素範圍d_first
- 新範圍的起始
返回值
指向最後被複制元素後一元素的迭代器。
示例
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
std::vector<int> v({1,2,3});
for (const auto& value : v) {
std::cout << value << " ";
}
std::cout << '\n';
std::vector<int> destination(3);
std::reverse_copy(std::begin(v), std::end(v), std::begin(destination));
for (const auto& value : destination) {
std::cout << value << " ";
}
std::cout << '\n';
}
排序操作
定義於標頭檔案 <algorithm>
sort
定義
template< class RandomIt >
void sort( RandomIt first, RandomIt last );
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
功能
以升序排序範圍 [first, last) 中的元素。不保證維持相等元素的順序。
-
- 用 operator< 比較元素。
-
- 用給定的二元比較函式 comp 比較元素。
引數
first
,last
- 要排序的元素範圍policy
- 所用的執行策略。細節見執行策略。comp
- 比較函式物件(即滿足比較 (Compare) 概念的物件),若第一引數小於(即先序於)第二引數則返回true
。
比較函式的簽名應等價於如下:
bool cmp(const Type1 &a, const Type2 &b);
示例
#include <algorithm>
#include <functional>
#include <array>
#include <iostream>
int main()
{
std::array<int, 10> s = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
// 用預設的 operator< 排序
std::sort(s.begin(), s.end());
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// 用標準庫比較函式物件排序
std::sort(s.begin(), s.end(), std::greater<int>());
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// 用自定義函式物件排序
struct {
bool operator()(int a, int b) const
{
return a < b;
}
} customLess;
std::sort(s.begin(), s.end(), customLess);
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// 用 lambda 表示式排序
std::sort(s.begin(), s.end(), [](int a, int b) {
return b < a;
});
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
}
最小/最大操作
max
定義
template< class T >
const T& max( const T& a, const T& b );
template< class T, class Compare >
const T& max( const T& a, const T& b, Compare comp );
template< class T >
T max( std::initializer_list<T> ilist );
template< class T, class Compare >
T max( std::initializer_list<T> ilist, Compare comp );
功能
返回給定值中的較大者。
- 1-2) 返回
a
與b
的較大者。 - 3-4) 返回
initializer_list ilist
中值的最大者。 - (1,3) 版本用
operator<
比較元素, (2,4) 版本用給定的比較函式comp
。
引數
a
,b
- 要比較的值ilist
- 擁有要比較的值的initializer_list
cmp
- 比較函式物件(即滿足比較 (Compare) 要求的物件),若若a
小於b
,則返回true
。
比較函式的簽名應等價於如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
- 1-2)
a
與b
的較大者。若它們等價,則返回a
。 - 3-4)
ilist
中的最大值。若有數個等價於最大者的值,則返回最左側的這種值。
示例
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::cout << "larger of 1 and 9999: " << std::max(1, 9999) << '\n'
<< "larger of 'a', and 'b': " << std::max('a', 'b') << '\n'
<< "longest of \"foo\", \"bar\", and \"hello\": " <<
std::max( { "foo", "bar", "hello" },
[](const std::string& s1, const std::string& s2) {
return s1.size() < s2.size();
}) << '\n';
}
max_element
定義
template< class ForwardIt >
ForwardIt max_element(ForwardIt first, ForwardIt last );
template< class ForwardIt, class Compare >
ForwardIt max_element(ForwardIt first, ForwardIt last, Compare comp );
功能
尋找範圍 [first, last)
中的最大元素。
1) 用 operator<
比較元素。
2) 用給定的二元比較函式 comp
比較元素。
引數
first
,last
- 定義要檢驗範圍的向前迭代器comp
- 比較函式物件(即滿足比較 (Compare) 要求的物件),若首個引數小於第二個,則返回true
。
比較函式的簽名應等價於如下:
bool cmp(const Type1 &a, const Type2 &b);
示例
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
static bool abs_compare(int a, int b)
{
return (std::abs(a) < std::abs(b));
}
int main()
{
std::vector<int> v{ 3, 1, -14, 1, 5, 9 };
std::vector<int>::iterator result;
result = std::max_element(v.begin(), v.end());
std::cout << "max element at: " << std::distance(v.begin(), result) << '\n';
result = std::max_element(v.begin(), v.end(), abs_compare);
std::cout << "max element (absolute) at: " << std::distance(v.begin(), result);
}
min
定義
template< class T >
const T& min( const T& a, const T& b );
template< class T, class Compare >
const T& min( const T& a, const T& b, Compare comp );
template< class T >
T min( std::initializer_list<T> ilist );
template< class T, class Compare >
T min( std::initializer_list<T> ilist, Compare comp );
功能
返回給定值中的較小者。
- 1-2) 返回
a
與b
的較小者。 - 3-4) 返回
initializer_list ilist
中值的最小者。 - (1,3) 版本用
operator<
比較元素, (2,4) 版本用給定的比較函式comp
。
引數
a
,b
- 要比較的值ilist
- 擁有要比較的值的initializer_list
cmp
- 比較函式物件(即滿足比較 (Compare) 要求的物件),若a
小於b
,則返回true
。
比較函式的簽名應等價於如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
- 1-2)
a
與b
的較小者。若值等價,則返回a
。 - 3-4)
ilist
中的最小值。若有數個等價於最小者的值,則返回最左側的這種值。
警告
若引數之一是右值,且返回該引數,則以引用捕獲 std::min
的結果會產生一個懸垂引用:
int n = 1;
const int& r = std::min(n-1, n+1);
// r 為懸垂
示例
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::cout << "smaller of 1 and 9999: " << std::min(1, 9999) << '\n'
<< "smaller of 'a', and 'b': " << std::min('a', 'b') << '\n'
<< "shortest of \"foo\", \"bar\", and \"hello\": " <<
std::min( { "foo", "bar", "hello" },
[](const std::string& s1, const std::string& s2) {
return s1.size() < s2.size();
}) << '\n';
}
輸出
smaller of 1 and 9999: 1
smaller of 'a', and 'b': a
shortest of "foo", "bar", and "hello": foo
min_element
定義
template< class ForwardIt >
ForwardIt min_element( ForwardIt first, ForwardIt last );
template< class ForwardIt, class Compare >
ForwardIt min_element( ForwardIt first, ForwardIt last, Compare comp );
功能
尋找範圍 [first, last)
中的最小元素。
1) 用 operator<
比較元素。
2) 用給定的二元比較函式 comp
比較元素。
引數
first
,last
- 定義要檢驗範圍的向前迭代器comp
- 比較函式物件(即滿足比較 (Compare) 要求的物件),若a
小於b
,則返回true
。
比較函式的簽名應等價於如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
指向範圍 [first, last)
中最小元素的迭代器。若範圍中有多個元素等價於最小元素,則返回指向首個這種元素的迭代器。若範圍為空則返回 last
。
示例
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{3, 1, 4, 1, 5, 9};
std::vector<int>::iterator result = std::min_element(std::begin(v), std::end(v));
std::cout << "min element at: " << std::distance(std::begin(v), result);
}
排列操作
定義於標頭檔案 <algorithm>
next_permutation
定義
template< class BidirIt >
bool next_permutation( BidirIt first, BidirIt last );
template< class BidirIt, class Compare >
bool next_permutation( BidirIt first, BidirIt last, Compare comp );
功能
變換範圍 [first, last)
為來自所有按相對於 operator<
或 comp
的字典序的下個排列。若這種排列存在則返回 true
,否則變換範圍為首個排列(如同用 std::sort(first, last)
)並返回 false
。
引數
first
,last
- 要重排的元素範圍comp
- 比較函式物件(即滿足比較 (Compare) 要求的物件),若首個引數小於第二個,則返回true
。
比較函式的簽名應等價於如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
若新排列按字典序大於舊者則為 true
。若抵達最後重排並重置範圍為首個排列則為 false
。
示例
下列程式碼列印字串 “aba
“ 的全部三種排列
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "aba";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
}
prev_permutation
定義
template< class BidirIt >
bool prev_permutation( BidirIt first, BidirIt last);
template< class BidirIt, class Compare >
bool prev_permutation( BidirIt first, BidirIt last, Compare comp);
功能
變換範圍 [first, last)
為來自於相對於 operator<
或 comp
的字典序的所有排列集合的上個排列。若這種排列存在則返回 true
,否則變換範圍為末排列(如同用 std::sort(first, last); std::reverse(first, last);
)並返回 false
。
返回值
若新排列按字典序前趨舊排列則為 true
。若抵達首個排列並重置範圍為最末排列則為 false
。
示例
下列程式碼以逆序列印字串 “abc
“ 的所有六個排列
#include <algorithm>
#include <string>
#include <iostream>
#include <functional>
int main()
{
std::string s="abc";
std::sort(s.begin(), s.end(), std::greater<char>());
do {
std::cout << s << ' ';
} while(std::prev_permutation(s.begin(), s.end()));
std::cout << '\n';
}