1. 程式人生 > 實用技巧 >C++ algorithm基操

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 - 目標範圍的起始,可以等於 first1first2
  • 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) 中的元素。不保證維持相等元素的順序。

    1. 用 operator< 比較元素。
    1. 用給定的二元比較函式 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) 返回 ab 的較大者。
  • 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) ab 的較大者。若它們等價,則返回 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) 返回 ab 的較小者。
  • 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) ab 的較小者。若值等價,則返回 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';
}