Bootstrap

C++ STL Algorithm 算法

Algorithm 算法

STL 算法部分主要由头文件,,组成。
要使用 STL 中的算法函数必须包含头文件,
对于数值算法须包含,
中则定义了一些模板类,用来声明函数对象。

排序

| 函数名           | 函数功能                                                                 | 函数声明                                                                 |
|-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| sort            | 以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。                     | template<class RanIt> void sort(RanIt first, RanIt last);                |
|                 |                                                                        | template<class RanIt, class Pred> void sort(RanIt first, RanIt last, Pred pr); |
| stable_sort     | 与 sort 类似,不过保留相等元素之间的顺序关系。                                | template<class BidIt> void stable_sort(BidIt first, BidIt last);         |
|                 |                                                                        | template<class BidIt, class Pred> void stable_sort(BidIt first, BidIt last, Pred pr); |
| partition       | 对指定范围内元素重新排序,使用输入的函数,把结果为 true 的元素放在结果为 false 的元素之前。 | template<class BidIt, class Pred> BidIt partition(BidIt first, BidIt last, Pred pr); |
| stable_partition| 与 partition 类似,不过不保证保留容器中的相对顺序。                          | template<class FwdIt, class Pred> FwdIt stable_partition(FwdIt first, FwdIt last, Pred pr); |
| random_shuffle  | 对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作。                 | template<class RanIt> void random_shuffle(RanIt first, RanIt last);      |
|                 |                                                                        | template<class RanIt, class Fun> void random_shuffle(RanIt first, RanIt last, Fun& f); |

sort()

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(int &v)
{
    cout<<v<<" ";
}
int main()
{
    vector<int> vi;
    for(int i=0; i<5; i++) vi.push_back(i);

    sort(vi.begin(),vi.end(),greater<int>());
    sort(vi.begin(),vi.end(),less_equal<int>());
    stable_sort(vi.begin(),vi.end(),greater_equal<int>());
    for_each(vi.begin(),vi.end(),print);
    return 0;
}

partition()

#include <iostream>
#include <vector>
#include <algorithm> // 包含partition和stable_partition的头文件

using namespace std;

// 判断一个整数是否为奇数的函数
bool isodd(int i)
{
    return (i % 2) == 1; // 如果i是奇数,返回true;否则返回false
}

int main()
{
    // 定义一个包含10个整数的数组
    int data[10] = {3, 6, 9, 2, 5, 8, 1, 4, 7, 0};

    // 使用数组data初始化一个vector
    vector<int> vi(data, data + 10);

    // 使用partition函数将vector中的元素按isodd函数的返回值进行分区
    // 奇数会被移动到vector的前面,偶数会被移动到vector的后面
    auto it = partition(vi.begin(), vi.end(), isodd);

     
    // stable_partition(vi.begin(), vi.end(), isodd);

    sort(vi.begin(),it,less<int>()); // 排序前半部分
    sort(it, vi.end(), less<int>()); // 排序后半部分
    // 遍历并输出vector中的所有元素
    for (auto i : vi)
    {
        cout << i << endl;
    }

    return 0;
}

random_shuffle()

random_shuffle 在C++11及以后的版本中已经被弃用,取而代之的是 std::shuffle 函数

std::random_shuffle 使用的是 rand 函数,
而 std::shuffle 使用的是更现代的随机数生成器(如 std::default_random_engine)。

std::shuffle 提供了更好的随机性和灵活性,因此推荐在C++11及以后的标准中使用 std::shuffle。

#include <iostream>
#include <algorithm> // 包含 random_shuffle
#include <vector>
#include <ctime>
#include <cstdlib> // 包含 srand 和 rand

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 设置随机种子
    std::srand(std::time(0));

    // 使用 random_shuffle 打乱 vector
    std::random_shuffle(vec.begin(), vec.end());

    // 输出打乱后的 vector
    for (int i : vec) {
        std::cout << i << " ";
    }

    return 0;
}

使用 std::shuffle

#include <iostream>
#include <algorithm> // 包含 shuffle
#include <vector>
#include <random> // 包含 default_random_engine

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 创建随机数生成器
    std::random_device rd;
    std::default_random_engine rng(rd());

    // 使用 shuffle 打乱 vector
    std::shuffle(vec.begin(), vec.end(), rng);

    // 输出打乱后的 vector
    for (int i : vec) {
        std::cout << i << " ";
    }

    return 0;
}

查找

| 函数名     | 函数功能                                                                 | 函数声明                                                                 |
|------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| find       | 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较.当匹配时,结束搜索,返回该元素的一个 InputIterator | template<class InIt, class T> InIt find(InIt first, InIt last, const T& val); |
| find_if    | 使用输入的函数代替等于操作符,执行 find                                   | template<class InIt, class Pred> InIt find_if(InIt first, InIt last, Pred pr); |
| count      | 利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数           | template<class InIt, class Dist> size_t count(InIt first, InIt last, const T& val, Dist& n); |
| count_if   | 利用输入的操作符,对标志范围内的元素进行操作,返回结果为 true 的个数     | template<class InIt, class Pred, class Dist> size_t count_if(InIt first, InIt last, Pred pr); |
| search     | 给出两个范围,返回一个 ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向 last1,重载版本使用自定义的比较操作 | template<class FwdIt1, class FwdIt2> FwdIt1 search(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2); |
|            |                                                                        | template<class FwdIt1, class FwdIt2, class Pred> FwdIt1 search(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2, Pred pr); |
| search_n   | 在指定范围内查找 val 出现 n 次的子序列。重载版本使用自定义的比较操作    | template<class FwdIt, class Dist, class T> FwdIt search_n(FwdIt first, FwdIt last, Dist n, const T& val); |
|            |                                                                        | template<class FwdIt, class Dist, class T, class Pred> FwdIt search_n(FwdIt first, FwdIt last, Dist n, const T& val, Pred pr); |

find()

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 定义一个函数,判断输入的整数是否大于等于3
bool func(int & v)
{
    return v >= 3 ? true : false;
}

int main()
{
    // 定义一个包含5个整数的数组
    int data[5] = {1, 2, 3, 4, 5};
    
    // 使用std::find查找数组中第一个值为4的元素
    int *p = find(data, data + 5, 4);
    if (p != data + 5)
        printf("%d\n", *p); // 如果找到,打印该值
    else
        printf("find none\n"); // 如果未找到,打印"find none"

    // 将数组转换为vector
    vector<int> vi(data, data + 5);
    
    // 使用std::find查找vector中第一个值为10的元素
    vector<int>::iterator itr;
    itr = find(vi.begin(), vi.end(), 10);
    if (itr != vi.end())
        cout << *itr << endl; // 如果找到,打印该值
    else
        cout << "find none" << endl; // 如果未找到,打印"find none"

    // 使用std::find_if查找vector中第一个满足func条件的元素
    itr = find_if(vi.begin(), vi.end(), func);
    if (itr != vi.end())
        cout << *itr << endl; // 如果找到,打印该值
    else
        cout << "find none" << endl; // 如果未找到,打印"find none"

    return 0;
}

count

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

// 定义一个函数,判断输入的整数是否大于10
bool func(int &v)
{
    return v > 10 ? true : false;
}

int main()
{
    // 定义一个包含8个整数的数组
    int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};
    
    // 使用std::count统计数组中值为10的元素个数
    int mycount = count(myints, myints + 8, 10);
    cout << "10 appears " << mycount << " times.\n";

    // 将数组转换为vector
    vector<int> myvector(myints, myints + 8);
    
    // 使用std::count统计vector中值为20的元素个数
    mycount = count(myvector.begin(), myvector.end(), 20);
    cout << "20 appears " << mycount << " times.\n";

    // 使用std::count_if统计vector中满足func条件的元素个数
    mycount = count_if(myvector.begin(), myvector.end(), func);
    cout << ">10 appears " << mycount << " times.\n";

    return 0;
}

search

#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

// 定义一个模板函数,判断字符串s是否在容器cont中
template<typename Container>
bool inQuote(const Container& cont, const string& s)
{
    // 使用std::search查找s在cont中的位置
    return search(cont.begin(), cont.end(), s.begin(), s.end()) != cont.end();
}

int main()
{
    // 定义一个字符串
    string str = "why waste time learning, when ignorance is instantaneous?";
    
    // 使用inQuote函数判断"learning"和"lemming"是否在字符串str中
    cout << boolalpha << inQuote(str, "learning") << '\n'
         << inQuote(str, "lemming") << '\n';

    // 将字符串转换为vector<char>
    vector<char> vec(str.begin(), str.end());
    
    // 使用inQuote函数判断"learning"和"lemming"是否在vector<char> vec中
    cout << boolalpha << inQuote(vec, "learning") << '\n'
         << inQuote(vec, "lemming") << '\n';

    return 0;
}

#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;

// 定义一个模板函数,判断容器c中是否存在连续count个值为v的元素
template <class Cont, class Size, class T>
bool consecutive_values(const Cont& c, Size count, const T& v)
{
    // 使用std::search_n查找容器c中是否存在连续count个值为v的元素
    return search_n(begin(c), end(c), count, v) != end(c);
}

int main()
{
    // 定义一个字符数组
    const char sequence[] = "1001010100010101001010101";
    
    // 设置输出为布尔值形式
    cout << boolalpha;
    
    // 判断字符数组中是否存在连续4个'0'
    cout << "Has 4 consecutive zeros: "
         << consecutive_values(sequence, 4, '0') << endl;
    
    // 判断字符数组中是否存在连续3个'0'
    cout << "Has 3 consecutive zeros: "
         << consecutive_values(sequence, 3, '0') << endl;

    return 0;
}

删除与替换

| 函数名          | 函数功能                                                                 | 函数声明                                                                 |
|-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| copy            | 复制序列                                                                 | template<class InIt, class OutIt> OutIt copy(InIt first, InIt last, OutIt x); |
| remove           | 删除指定范围内所有等于指定元素的元素。注意,该函数不是真正删除函数。内置函数不适合使用 remove 和 remove_if 函数 | template<class FwdIt, class T> FwdIt remove(FwdIt first, FwdIt last, const T& val); |
| remove_if        | 删除指定范围内输入操作结果为 true 的所有元素                             | template<class FwdIt, class Pred> FwdIt remove_if(FwdIt first, FwdIt last, Pred pr); |
| remove_copy      | 将所有不匹配元素复制到一个制定容器,返回 OutputIterator 指向被拷贝的末元素的下一个位置 | template<class InIt, class OutIt, class T> OutIt remove_copy(InIt first, InIt last, OutIt x, const T& val); |
| remove_copy_if   | 将所有不匹配元素拷贝到一个指定容器                                       | template<class InIt, class OutIt, class Pred> OutIt remove_copy_if(InIt first, InIt last, OutIt x, Pred pr); |
| unique           | 清除序列中重复元素,和 remove 类似,它也不能真正删除元素。重载版本使用自定义比较操作 | template<class FwdIt> FwdIt unique(FwdIt first, FwdIt last); |
|                 |                                                                        | template<class FwdIt, class Pred> FwdIt unique(FwdIt first, FwdIt last, Pred pr); |
| unique_copy      | 与 unique 类似,不过把结果输出到另一个容器                               | template<class InIt, class OutIt> OutIt unique_copy(InIt first, InIt last, OutIt x); |
|                 |                                                                        | template<class InIt, class OutIt, class Pred> OutIt unique_copy(InIt first, InIt last, OutIt x, Pred pr); |

copy()

//todo copy
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
using namespace std;

int main()
{
    // 创建一个包含整数1到8的向量from
    vector<int> from = {1, 2, 3, 4, 5, 6, 7, 8};

    // 创建一个大小为10的向量to,初始值未定义
    vector<int> to(10);

    // 将from向量的内容复制到to向量中,从to的起始位置开始
    copy(from.begin(), from.end(), to.begin());

    // 调整to向量的大小,使其与from向量的大小相同
    to.resize(from.size());

    // 输出to向量的内容
    cout << "to_vector contains: ";

    // 使用copy算法将to向量的内容输出到标准输出,每个元素后跟一个空格
    copy(to.begin(), to.end(), ostream_iterator<int>(cout, " "));

    // 输出换行符
    cout << '\n';
}

.remove

#include <algorithm>
#include <string>
#include <iostream>
#include <cctype>
using namespace std;

int main()
{
    // 定义一个整数数组
    int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};

    // 定义数组的起始和结束指针
    int* pbegin = myints;
    int* pend = myints + sizeof(myints) / sizeof(int);

    // 使用std::remove移除数组中的值为20的元素
    pend = remove(pbegin, pend, 20);

    // 输出移除后的数组内容
    cout << "range contains:";
    for (int* p = pbegin; p != pend; ++p)
        cout << ' ' << *p;
    cout << '\n';

    return 0;
}

int main2()
{
    // 定义一个包含空格的字符串
    string str1 = "Text with some spaces";

    // 使用std::remove移除字符串中的空格
    str1.erase(remove(str1.begin(), str1.end(), ' '), str1.end());
    cout << str1 << '\n';

    // 定义一个包含多种空白字符的字符串
    string str2 = "Text\n with\tsome \t whitespaces\n\n";

    // 使用std::remove_if移除字符串中的所有空白字符
    str2.erase(remove_if(str2.begin(), str2.end(), [](char x) { return isspace(x); }), str2.end());
    cout << str2 << '\n';

    return 0;
}

unique 去除重复元素

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

int main()
{
    // 创建一个包含重复元素的向量
    vector<int> v = {1, 2, 3, 1, 2, 3, 3, 4, 5, 4, 5, 6, 7};
    
    // 对向量进行排序,以便相同的元素相邻
    sort(v.begin(), v.end());
    // 排序后的向量为:1 1 2 2 3 3 3 4 4 5 5 6 7

    // 使用unique算法移除相邻的重复元素,返回新的结束迭代器
    auto last = unique(v.begin(), v.end());
    // 此时向量v的内容为:1 2 3 4 5 6 7 x x x x x x,其中'x'是未定义的值

    // 使用erase方法移除向量中从last到end之间的元素,即移除多余的未定义值
    v.erase(last, v.end());

    // 输出向量v的内容
    for (int i : v)
        cout << i << " ";
    cout << "\n";

    // 处理字符串中的连续空格
    string s = "wanna go   to space?";

    // 使用unique算法移除连续的空格,自定义比较函数用于判断是否为连续空格
    auto end = unique(s.begin(), s.end(),
                      [](char l, char r){
                          return isspace(l) && isspace(r) && l == r;
                      });
    // 此时字符串s的内容为:"wanna go to space?xxxxxxxx",其中'x'是未定义的值

    // 输出处理后的字符串,只输出到end迭代器之前的内容
    cout << string(s.begin(), end) << '\n';

    return 0;
}

排列组合

| 函数名            | 函数功能                                                                 | 函数声明                                                                 |
|-------------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| next_permutation  | 取出当前范围内的排列,并重新排序为下一个排列。重载版本使用自定义的比较操作 | template<class BidIt> bool next_permutation(BidIt first, BidIt last); |
|                   |                                                                        | template<class BidIt, class Pred> bool next_permutation(BidIt first, BidIt last, Pred pr); |
| prev_permutation  | 取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回 false。重载版本使用自定义的比较操作 | template<class BidIt> bool prev_permutation(BidIt first, BidIt last); |
|                   |                                                                        | template<class BidIt, class Pred> bool prev_permutation(BidIt first, BidIt last, Pred pr); |

next_permutation

#include <iostream>
#include <algorithm>

int main ()
{
    // 定义一个包含三个整数的数组
    int myints[] = {1, 2, 3};
    
    // 对数组进行排序,确保初始顺序为升序
    std::sort (myints, myints + 3);
    
    // 输出提示信息
    std::cout << "The 3! possible permutations with 3 elements:\n";

    // 使用do-while循环来遍历所有可能的排列
    do
    {
        // 输出当前排列
        std::cout << myints[0] << ' '
                  << myints[1] << ' '
                  << myints[2] << '\n';
    // 使用std::next_permutation生成下一个排列,直到所有排列都被生成
    } while (std::next_permutation(myints, myints + 3));

    // 输出循环结束后数组的最终状态
    std::cout << "After loop: "
              << myints[0] << ' '
              << myints[1] << ' '
              << myints[2] << '\n';

    return 0;
}

prev_permutation

#include <iostream>
#include <algorithm>

int main ()
{
    // 定义一个包含三个整数的数组
    int myints[] = {1, 2, 3};
    
    // 对数组进行排序,确保初始顺序为升序
    std::sort (myints, myints + 3);
    
    // 输出提示信息
    std::cout << "The 3! possible permutations with 3 elements:\n";

    // 使用do-while循环来遍历所有可能的排列
    do
    {
        // 输出当前排列
        std::cout << myints[0] << ' '
                  << myints[1] << ' '
                  << myints[2] << '\n';
    // 使用std::prev_permutation生成上一个排列,直到所有排列都被生成
    } while (std::prev_permutation(myints, myints + 3));

    // 输出循环结束后数组的最终状态
    std::cout << "After loop: "
              << myints[0] << ' '
              << myints[1] << ' '
              << myints[2] << '\n';

    return 0;
}

集合

| 函数名          | 函数功能                                                                 | 函数声明                                                                 |
|-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| set_union       | 构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作 | template<class InIt1, class InIt2, class OutIt> OutIt set_union(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x); |
|                 |                                                                        | template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_union(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr); |
| set_difference  | 构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作 | template<class InIt1, class InIt2, class OutIt> OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x); |
|                 |                                                                        | template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr); |
| set_intersection| 构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作 | template<class InIt1, class InIt2, class OutIt> OutIt set_intersection(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x); |
|                 |                                                                        | template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_intersection(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr); |

set_union 判断两个集合的并集

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
    // 定义两个数组并初始化
    int first[5] = {1, 2, 5, 7, 9};
    int second[5] = {1, 2, 6, 8, 10};

    // 创建一个vector,预留20个整数的空间
    vector<int> vi(20);
    vector<int>::iterator itr;

    // 对两个数组进行排序
    sort(first, first + 5);
    sort(second, second + 5);

    // 使用set_union函数将两个数组的并集存储到vector中
    // set_union要求输入序列是有序的
    itr = set_union(first, first + 5, second, second + 5, vi.begin());

    // 调整vector的大小,使其只包含并集的元素
    vi.resize(itr - vi.begin());

    // 使用copy函数将vector中的元素输出到标准输出
    copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " "));

    return 0;
}

set_difference 判断两个集合的差集

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
    // 定义两个数组,分别包含一些整数
    int first[5] = {1, 2, 5, 7, 9};
    int second[5] = {1, 2, 6, 7, 10};

    // 创建一个大小为20的向量,用于存储结果
    vector<int> vi(20);

    // 定义一个迭代器,用于接收set_difference的结果
    vector<int>::iterator itr;

    // 对两个数组进行排序,确保它们是有序的
    sort(first, first + 5);
    sort(second, second + 5);

    // 使用set_difference算法,找出first数组中有而second数组中没有的元素,并存储到vi向量中
    // 返回值是一个迭代器,指向结果序列的结束位置
    itr = set_difference(first, first + 5, second, second + 5, vi.begin());

    // 调整vi向量的大小,使其只包含实际的结果元素
    vi.resize(itr - vi.begin());

    // 使用copy算法将结果输出到标准输出,每个元素之间用空格分隔
    copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " "));

    // 返回0,表示程序成功结束
    return 0;
}

set_intersection 判断两个集合的交集

#include <iterator>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    // 定义两个数组并初始化
    int first[5] = {1, 2, 5, 7, 9};
    int second[5] = {1, 2, 6, 8, 10};

    // 创建一个vector,预留20个整数的空间
    vector<int> vi(20);
    vector<int>::iterator itr;

    // 对两个数组进行排序
    sort(first, first + 5);
    sort(second, second + 5);

    // 使用set_intersection函数将两个数组的交集存储到vector中
    // set_intersection要求输入序列是有序的
    itr = set_intersection(first, first + 5, second, second + 5, vi.begin());

    // 调整vector的大小,使其只包含交集的元素
    vi.resize(itr - vi.begin());

    // 使用copy函数将vector中的元素输出到标准输出
    copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " "));

    return 0;
}

;