set_intersection、set_union、set_difference学习总结

        本博客中,我们将学习并总结常用的集合算法。
算法简介:

set_intersection //求2个容器的交集
set_union //求2个容器的并集
set_difference //求2个容器的差集

(这3个集合算法都要求必须是有序的容器的区间,否则一定会报异常!) 

一、set_intersection(intersection是交集的意思,so这里是求2个容器的交集)

功能描述:
    求两个集合(容器)的交集(求两个集合的交集,并把交集的元素都赋值给到一个目标容器中)
函数原型:

set_intersection(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);

    beg1:第一个容器的开始迭代器
    end1:第一个容器的结束迭代器
    beg2:第二个容器的开始迭代器
    end2:第二个容器的结束迭代器
    dest:目标容器的开始迭代器
总结:
    注意:set_intersection do 了交集只后就会返回一个迭代器,这个迭代器会 记录 你交集赋值给vTarget目标容器的最后一个元素返回这样一个迭代器,就可以让你更好的观察所看到的交集容器中的数据,而不是看到里面的一些无效的数据,比如没有vTarget.size()那么多个交集元素,那么多出来的元素    就会默认赋值为0,这些0就是无效的元素也只有这样你才能够拿到最正确的交集元素!
    注意:2个集合(容器)必须都是有序的序列无序的你都要先弄成有序的先!(sort/stable_sort)有序的才能正确do交的操作。无序的序列是不能取交集的!

简而言之:

    ①求交集的2个集合(容器)必须是有序的序列
    ②目标容器需要开辟的空间大小 == vTarget.resize( min( v1.size(),v2.size() ) );是从2个容器中取小的那个值
    ③set_intersection() 算法函数的返回值 就是交集中最后一个交集元素的位置处的迭代器!

test_codes1:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(void){
    vector<int> v1;
    v1.reserve(10);
    for(int i=0;i<10;++i)
        v1.push_back(i);
    //v1: 0 1 2 3 4 5 6 7 8 9
	for_each(v1.begin(), v1.end(), [](int v) { cout << v << "\t"; });cout << endl;
    vector<int> v2;
    v2.reserve(10);
    for(int i=5;i<15;++i)
        v2.push_back(i);
    //v2: 5 6 7 8 9 10 11 12 13 14
    for_each(v2.begin(),v2.end(),[](int val) {cout<<val<<"\t";}); cout<<endl;
    vector<int> vTarget;
    //目标容器肯定是要提前开辟空间的哇!!!
	//最特殊的case 是: 大容器包含小容器 此时 给目标容器开辟空间的话就要取 小容器的size即可!
	//而且,这也是 取交集 最特殊的case 取完交集之后,最多这个交集的size 就 == size小的那个容器的.size()而已
	//你都给目标容器开辟最大的空间了 那肯定没毛病的了!
    vTarget.reserve(min(v1.size(),v2.size()));
    cout << "before set_intersection(v1,v2,vTarget)取交集:" << endl;
	cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {
		cout << v << "\t"; });
	cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {
		cout << v << "\t"; });
	cout << endl;
	cout << "vTarget:" << endl;
	for_each(vTarget.begin(), vTarget.end(), [](int v) {
		cout << v << "\t"; });
	cout << endl;
	cout << "after set_intersection(v1,v2,vTarget)取交集:" << endl;
	auto it //拿到交集的结束迭代器
        = std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    cout << "v1:" << endl;
    for_each(v1.begin(), v1.end(), [](int v) {
        cout << v << "\t"; });
    cout << endl;
    cout << "v2:" << endl;
    for_each(v2.begin(), v2.end(), [](int v) {
        cout << v << "\t"; });
    cout << endl;
    cout << "vTarget:" << endl;
    // for_each(vTarget.begin(), vTarget.end(), [](int v) {
    //     cout << v << "\t"; });
    // cout << endl;
    for_each(vTarget.begin(), it, [](int v) {
        cout << v << "\t"; });
    cout << endl;

    vector<int> vTarget2;
    vTarget2.reserve(min(v1.size(),v2.size()));
    cout << "before set_intersection(v2,v1,vTarget2)取交集:" << endl;
	cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {
		cout << v << "\t"; });
	cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {
		cout << v << "\t"; });
	cout << endl;
	cout << "vTarget2:" << endl;
	for_each(vTarget2.begin(), vTarget2.end(), [](int v) {
		cout << v << "\t"; });
	cout << endl;
	cout << "after set_intersection(v2,v1,vTarget2)取交集:" << endl;
	auto it2 //拿到交集的结束迭代器
        = std::set_intersection(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget2.begin());
    cout << "v1:" << endl;
    for_each(v1.begin(), v1.end(), [](int v) {
        cout << v << "\t"; });
    cout << endl;
    cout << "v2:" << endl;
    for_each(v2.begin(), v2.end(), [](int v) {
        cout << v << "\t"; });
    cout << endl;
    cout << "vTarget2:" << endl;
    for_each(vTarget2.begin(), it2, [](int v) {
        cout << v << "\t"; });
    cout << endl;
    return 0;
}

运行结果:

 
二、set_union(union是并集的意思,so这里是求2个容器的并集)

功能描述:
      求2个集合(容器)的并集
    (所谓的并集,其实是2个容器中公共的不重复了的元素都可以是并集中的元素(或者说成为并集中的元素))也即并集中含有的元素不能重复!!!把2个集合(容器)并起来,把重复了的元素都删去(2个容器中的每个元素,只要不重复的,都只保留一次),那么剩下的就是2容器的并集!
函数原型:

set_union(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);

    注意:2个集合(容器)必须都是有序的序列无序的你都要先弄成有序的先!(sort/stable_sort)有序的才能正确do并的操作。
    beg1:容器1的开始迭代器
    end1:容器1的结束迭代器
    beg2:容器2的开始迭代器
    end2:容器2的结束迭代器
    dest:目标容器的开始迭代器

总结:
    ①求并集的两个集合(容器)必须都是 有序的序列
    ②目标容器vTarget所要开辟的空间 必须是2个原容器的size 之和
    ③set_union的返回值 就是并集中最后一个并集元素的位置处的迭代器
    用这个last一个并集元素的迭代器itEnd来 看 目标容器中的并集元素才是最正确直观的!

test_codes2:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(void){
    vector<int> v1{0,1,2,3,4};// 0 1 2 3 4
    vector<int> v2{2,3,4,5,6,7};// 2 3 4 5 6 7
    vector<int> vTarget;
    vTarget.resize(v1.size() + v2.size());
    //提前给 目标容器 开辟空间
	//求并集最特殊的case 就是两个容器一点交集都没有,那么并集 就是会包含这两个容器all的元素
	//此case 下,并集的size == 两个容器的size 相加
	//目标容器的size 最多最多就是原用于do并集的2个容器的size之和,也即vTarget.resize( v1.size() + v2.size() );
    cout<<"before set_union(v1,v2,vTarget):"<<endl;
	cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "vTarget:" << endl;
	for_each(vTarget.begin(), vTarget.end(), [](int v) {cout << v << "\t"; });cout << endl;
    cout<<"after set_union(v1,v2,vTarget):"<<endl;
    auto it //取得并集结束位置的迭代器
        = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
    cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "vTarget:" << endl;
	for_each(vTarget.begin(), vTarget.end(), [](int v) {cout << v << "\t"; });cout << endl;
    for_each(vTarget.begin(), it, [](int v) {cout << v << "\t"; });cout << endl;
    return 0;
}

运行结果:

三、set_difference(difference是差集的意思,so这里是求2个容器的差集,就是求两个容器都不相干的元素的集合)

功能描述:
    求2个集合(容器)的差集
函数原型:

set_difference(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);

    注意:2个集合(容器)必须都是有序的序列无序的你都要先弄成有序的先!(sort/stable_sort)有序的才能正确do差的操作。
    beg1 容器1的开始迭代器
    end1 容器1的结束迭代器
    beg2 容器2的开始迭代器
    end2 容器2的结束迭代器
    dest 目标容器的开始迭代器
总结:
    注意:求差集 要看你求 谁 和 谁 的差集,一般 v1和v2的差集,v2和v1的差集的结果都是不一样的!

比如:
    v1和v2的差集:也即在v1中去看v1和v2不重复的元素,这些元素就属于v1和v2的差集
    v2和v1的差集:也即在v2中去看v2和v1不重复的元素,这些元素就属于v2和v1的差集
如        v1: 0 1 2 3 4 5 6 7 8 9
          v2: 5 6 7 8 9 10 11 12 13 14
    v1和v2的差集是: 0 1 2 3 4
    v2和v1的差集是:10 11 12 13 14    
    求差集的两个集合(容器)必须的是有序的序列
    目标容器的开辟空间 必须是 vTarget.resize( max( v1.size(), v2.size() ) );

test_codes3:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(void){
    vector<int> v1{0,1,2,3,4};// 0 1 2 3 4
    vector<int> v2{2,3,4,5,6,7};// 2 3 4 5 6 7
    vector<int> vTarget;
    vTarget.resize(max(v1.size(),v2.size()));
    //提前给 目标容器 开辟空间
	//取差集的最特殊case 就是取 v1 和 v2 两个容器的 最大的那个v的size了(比如v1和v2完全没有交集这种case)
    cout<<"before set_difference(v1,v2,vTarget):"<<endl;
	cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "vTarget:" << endl;
	for_each(vTarget.begin(), vTarget.end(), [](int v) {cout << v << "\t"; });cout << endl;
    cout<<"after set_difference(v1,v2,vTarget):"<<endl;
    auto it //取得并集结束位置的迭代器
        = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
    cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "vTarget:" << endl;
	for_each(vTarget.begin(), vTarget.end(), [](int v) {cout << v << "\t"; });cout << endl;
    for_each(vTarget.begin(), it, [](int v) {cout << v << "\t"; });cout << endl;

    vector<int> vTarget2;
    vTarget2.resize(vTarget.size());
    //提前给 目标容器 开辟空间
	//取差集的最特殊case 就是取 v1 和 v2 两个容器的 最大的那个v的size了(比如v1和v2完全没有交集这种case)
    cout<<"before set_difference(v2,v1,vTarget2):"<<endl;
	cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "vTarget2:" << endl;
	for_each(vTarget2.begin(), vTarget2.end(), [](int v) {cout << v << "\t"; });cout << endl;
    cout<<"after set_difference(v2,v1,vTarget2):"<<endl;
    auto it2 //取得并集结束位置的迭代器
        = set_difference(v2.begin(),v2.end(),v1.begin(),v1.end(),vTarget2.begin());
    cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "v2:" << endl;
	for_each(v2.begin(), v2.end(), [](int v) {cout << v << "\t"; });cout << endl;
	cout << "vTarget:" << endl;
	for_each(vTarget2.begin(), vTarget2.end(), [](int v) {cout << v << "\t"; });cout << endl;
    for_each(vTarget2.begin(), it2, [](int v) {cout << v << "\t"; });cout << endl;
    return 0;
}

运行结果:

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Fanfan21ya

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

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

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

打赏作者

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

抵扣说明:

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

余额充值