C++学习笔记(四十一)——STL之合并与排列组合算法

STL 算法分类:

类别常见算法作用
排序sortstable_sortpartial_sortnth_element排序
搜索findfind_ifcountcount_ifbinary_search查找元素
修改copyreplacereplace_ifswapfill修改容器内容
删除removeremove_ifunique删除元素
归约for_eachaccumulate处理数据
合并mergeset_unionset_intersection处理有序序列
排列组合next_permutationprev_permutation生成排列
堆操作push_heappop_heapmake_heapsort_heap处理堆

一、STL 合并算法

STL 中的合并算法(Merge Algorithms)用于将两个有序的序列(通常是容器中的元素)合并成一个新的有序序列。
这些算法包括 mergeinplace_merge等。

算法名称功能描述时间复杂度空间复杂度适用场景
merge合并两个有序范围并返回一个新的有序范围O(n + m)O(n + m)合并两个有序序列并返回合并结果
inplace_merge合并两个相邻的有序范围,原地操作O(n)O(1)合并相邻的有序范围,在原地进行合并
set_union计算两个有序范围的并集,去除重复元素O(n + m)O(n + m)计算两个有序序列的并集
set_intersection计算两个有序范围的交集O(n + m)O(min(n, m))计算两个有序序列的交集
set_difference计算两个有序范围的差集,返回第一个范围独有的元素O(n + m)O(n)计算两个有序序列的差集

(1)merge

  • 功能:将两个有序的容器(或范围)合并成一个新的有序容器。该算法返回一个指向结果容器末尾的迭代器。
  • 时间复杂度O(n + m),其中 nm 是两个输入序列的长度。
  • 空间复杂度O(n + m),需要额外的存储空间来存储合并结果。

示例:

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

int main() {
    vector<int> vec1 = { 1, 3, 5, 7 };
    vector<int> vec2 = { 2, 4, 6, 8 };
    vector<int> result(vec1.size() + vec2.size());

    // 合并 vec1 和 vec2,结果存储在 result 中
    merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());

    cout << "Merged result: ";
    for (int num : result)
    {
        cout << num << " ";  // 输出:1 2 3 4 5 6 7 8
    }
    cout << endl;

    system("pause");
    return 0;
}

注意:

  • merge用于合并两个有序范围(容器、数组等),并将结果保存到第三个容器中。

(2)inplace_merge

  • 功能:将两个相邻的有序范围合并成一个有序范围,而不需要额外的存储空间。
    该算法要求容器中这两个有序范围是连续的,并且只会在原地操作。
  • 时间复杂度O(n),其中 n 是这两个范围元素的总数。
  • 空间复杂度O(1),原地操作。

示例:

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

int main() {
    vector<int> vec = { 1, 3, 5, 7, 2, 4, 6, 8 };

    // 将 vec 中前四个元素和后四个元素合并
    inplace_merge(vec.begin(), vec.begin() + 4, vec.end());

    cout << "Inplace merged result: ";
    for (int num : vec)
    {
        cout << num << " ";  // 输出:1 2 3 4 5 6 7 8
    }
    cout << endl;

    system("pause");
    return 0;
}

注意:

  • inplace_merge用于在原地合并两个相邻的有序范围,通常适用于某些排序算法(如归并排序)。

(3)set_union

  • 功能:计算两个有序范围的并集,去除重复元素,并将结果存储在目标范围中。
  • 时间复杂度O(n + m),其中 nm 是两个输入范围的长度。
  • 空间复杂度O(n + m),需要额外的存储空间来存储合并结果。

示例:

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

int main() {
    vector<int> vec1 = { 1, 3, 5, 7 };
    vector<int> vec2 = { 2, 4, 6, 8 };
    vector<int> result(vec1.size() + vec2.size());

    // 计算并集
    auto it = set_union(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());

    cout << "并集结果: ";
    for (auto i = result.begin(); i != it; ++i)
    {
        cout << *i << " ";  // 输出:1 2 3 4 5 6 7 8
    }
    cout << endl;

    system("pause");
    return 0;
}

注意:

  • set_union适用于,当需要计算两个有序序列的并集时。

(4)set_intersection

  • 功能:计算两个有序范围的交集,并将结果存储在目标范围中。交集中的元素是两个范围都包含的元素。
  • 时间复杂度O(n + m),其中 nm 是两个输入范围的长度。
  • 空间复杂度O(min(n, m)),需要额外的存储空间来存储合并结果。

示例:

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

int main() {
    vector<int> vec1 = { 1, 3, 5, 7 };
    vector<int> vec2 = { 3, 5, 7, 9 };
    vector<int> result(min(vec1.size(), vec2.size()));

    // 计算交集
    auto it = set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());

    cout << "交集结果: ";
    for (auto i = result.begin(); i != it; ++i)
    {
        cout << *i << " ";  // 输出:3 5 7
    }
    cout << endl;

    system("pause");
    return 0;
}

注意:

  • set_intersection适用于,当需要计算两个有序序列的交集时。

(5)set_difference

  • 功能:计算两个有序范围的差集,返回在第一个范围中但不在第二个范围中的元素。
  • 时间复杂度O(n + m),其中 nm 是两个输入范围的长度。
  • 空间复杂度O(n),最多为第一个集合的长度。

示例:

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

int main() {
    vector<int> vec1 = { 1, 3, 5, 7 };
    vector<int> vec2 = { 3, 5, 7, 9 };
    vector<int> result(vec1.size());

    // 计算差集
    auto it = set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());

    cout << "差集结果: ";
    for (auto i = result.begin(); i != it; ++i)
    {
        cout << *i << " ";  // 输出:1
    }
    cout << endl;

    system("pause");
    return 0;
}

注意:

  • set_difference适用于,当需要计算两个有序序列的差集时。

二、STL 排列组合算法

STL 提供了一些用于生成排列和组合的算法,主要用于在容器中生成元素的排列或组合。
这些算法可以广泛应用于算法设计、组合数学以及其他场景中。

算法名称功能描述时间复杂度空间复杂度适用场景
next_permutation生成下一个字典序排列O(n)O(1)用于生成所有排列,直到没有更多的排列为止
prev_permutation生成上一个字典序排列O(n)O(1)用于生成所有排列的逆向排列
shuffle随机打乱元素顺序O(n)O(1)用于随机排列容器元素

(1)next_permutation

  • 功能:生成容器元素的下一个字典序排列。返回值表示是否成功生成下一个排列。
  • 时间复杂度O(n),其中 n 是容器中的元素数量。
  • 空间复杂度O(1),原地操作。

示例:

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

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

    do 
    {
        for (int i : vec) 
        {
            cout << i << " ";
        }
        cout << endl;
    } while (next_permutation(vec.begin(), vec.end()));

    system("pause");
    return 0;
}

注意:

  • next_permutation用于生成元素的所有排列(字典序),直到没有更多的排列为止。

(2)prev_permutation

  • 功能:生成容器元素的上一个字典序排列。返回值表示是否成功生成上一个排列。
  • 时间复杂度O(n),其中 n 是容器中的元素数量。
  • 空间复杂度O(1),原地操作。

示例:

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

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

    do 
    {
        for (int i : vec) 
        {
            cout << i << " ";
        }
        cout << endl;
    } while (prev_permutation(vec.begin(), vec.end()));

    system("pause");
    return 0;
}

注意:

  • prev_permutation用于从当前排列开始生成之前的排列。

(3)shuffle

  • 功能:用于打乱容器元素的顺序。通过随机数生成器控制打乱的顺序,产生所有可能的排列之一。
  • 时间复杂度O(n),其中 n 是容器的大小。
  • 空间复杂度O(1),原地操作。

示例:

#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // shuffle
#include <random>

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

    // 使用随机数生成器进行打乱
    random_device rd;
    mt19937 g(rd());

    shuffle(vec.begin(), vec.end(), g);

    cout << "打乱顺序后的容器: ";
    for (int i : vec)
    {
        cout << i << " ";
    }
    cout << endl;

    system("pause");
    return 0;
}

注意:

  • shuffle适用于,当需要随机排列容器元素时。
  • ‌mt19937‌是基于梅森旋转算法(Mersenne Twister)的伪随机数生成器,属于高质量伪随机数算法的一种实现形式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奕天者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值