std::set得交集应用[笔记]

本文通过一个C++示例程序介绍了如何使用自定义比较器对字符串集合进行操作,包括集合的创建、插入元素及两个集合间的交集运算。
1、比如一些电话号码比较,如果文件比较大考虑插桩!
2、时间段重叠运算。
3、数据变化处理。

#include "stdafx.h"
#include <set>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;

struct compare
{
bool operator ()(string s1,string s2)
{
return s1 > s2;
}///自定义一个仿函数
};
int main()
{
typedef std::set<string,compare> _SET;
_SET s;
s.insert(string("sfdsfd"));
s.insert(string("apple"));
s.insert(string("english"));
s.insert(string("dstd"));
cout<<"s1:"<<endl;
std::set<string,compare>::iterator it = s.begin();
while(it!=s.end())
cout<<*it++<<" ";
cout<<endl<<"s2:"<<endl;
_SET s2;
s2.insert(string("abc"));
s2.insert(string("apple"));
s2.insert(string("english"));
it = s2.begin();
while(it!=s2.end())
cout<<*it++<<" ";
cout<<endl<<endl;

string str[10];
string *end = set_intersection(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());
cout<<"result of set_intersection s1 <> s2:"<<endl;
string *first = str;
while(first<end)
cout <<*first++<<" ";
cout <<endl;
}
<think>好的,我现在需要解决用户的问题:如何用C++ STL计算两个std::vector<std::set<int>>容器内对应位置集合的交集和差集,并将结果存入新容器。首先,我需要理清用户的需求。用户有两个vector,每个元素都是set<int>,他们希望逐一对每个对应的set进行交集和差集操作,然后将结果保存到新的vector中。 首先,我得确认用户的数据结构。两个vector的每个元素都是set<int>,并且是按位置对应的,也就是说第一个vector的第i个set和第二个vector的第i个set进行操作。这要求两个vector的大小必须相同,否则会出问题。不过用户可能已经确保这一点,或者需要代码中做检查,但用户的问题中没有提到,可能需要考虑,但暂时先假设大小相同。 接下来,如何逐个处理对应的set。对于每个位置i,取vector1[i]和vector2[i]的set,计算它们的交集和差集。差集可能有不同的方向,比如A-B或B-A,用户需要哪一种?用户的问题中没有明确说明,可能需要同时处理两种差集,或者只处理一种。根据引用[3]中的内容,差集的方向取决于参数的顺序,所以可能需要用户指定,但根据问题描述,用户可能希望得到两个容器对应位置的差集,可能是指每个元素各自的差集,比如A-B和B-A,或者只是其中一种。不过用户的问题里提到“差集”,可能需要明确。但根据用户提供的引用,特别是引用[3]中的例子,如果要求A-B,就是set_difference(a.begin(), a.end(), b.begin(), b.end(), ...),而B-A则是交换参数位置。所以可能需要用户明确差集的方向,但问题中可能希望得到两个差集结果吗?或者只其中一个? 不过用户的问题中,他说“交集与差集”,可能希望每个对应的位置得到一个交集和一个差集的结果,例如,每个元素得到一个交集的结果集和一个差集的结果集。因此,可能需要生成两个新的vector<set<int>>,一个存放所有交集,另一个存放所有差集。或者,用户可能希望将交集和差集都存入同一个结构,但根据问题描述,更可能是分别存储。 现在,如何用STL算法来实现这一点。根据引用[1]、[2]、[3],特别是引用[3]中提到的set_intersection和set_difference函数,这些函数用于两个有序集合的交集和差集计算。因为set本身是有序的,所以可以直接使用这些算法。 具体步骤应该是: 1. 确保两个vector的大小相同,否则无法对应处理。 2. 创建两个新的vector<set<int>>,分别用于存储交集和差集的结果。 3. 遍历两个输入vector的每个对应位置的set。 4. 对每对set,使用std::set_intersection计算交集,并插入到交集的vector中。 5. 同样,使用std::set_difference计算差集(比如A-B),并插入到差集的vector中。 6. 返回这两个新的vector作为结果。 需要注意的是,std::set_intersection和std::set_difference需要目标容器使用插入迭代器,比如std::back_inserter或者直接插入到set中。然而,set的插入可能需要使用inserter,因为set的back_inserter可能不适用,因为set没有push_back方法。但在这里,每个结果是一个set<int>,所以对于每个位置i的交集,应该创建一个新的set<int>,然后使用std::inserter来填充这个set。 例如,对于两个set<int> a和b,交集可以这样计算: std::set<int> intersect; std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(intersect, intersect.begin())); 同理,差集: std::set<int> diff; std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(diff, diff.begin())); 然后,将intersect和diff分别添加到结果vector中。 现在,针对两个vector<set<int>>的操作,需要遍历每个元素,并执行上述操作。因此,代码的大致结构可能是这样的: std::vector<std::set<int>> vec1, vec2; // 假设vec1和vec2已经初始化,并且大小相同 std::vector<std::set<int>> intersections; std::vector<std::set<int>> differences; for (size_t i = 0; i < vec1.size(); ++i) { const auto& set1 = vec1[i]; const auto& set2 = vec2[i]; std::set<int> intersect; std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), std::inserter(intersect, intersect.begin())); std::set<int> diff; std::set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), std::inserter(diff, diff.begin())); intersections.push_back(intersect); differences.push_back(diff); } 这样,intersections和differences分别保存了每个对应位置集合的交集和差集(A-B)。 需要注意的是,std::set_intersection和std::set_difference要求输入的范围是有序的,而std::set本身是有序的,所以这里没问题。此外,结果集需要用inserter来插入元素,因为set的迭代器是const的,不能直接写入。 用户的问题中还提到,结果需要存入新容器,也就是这两个新的vector。 另外,是否需要处理vec1和vec2的大小不一致的情况?在代码中,可能需要先检查两个vector的大小是否相同,否则循环会越界。所以,在代码中应该添加一个assert或者条件判断,比如: assert(vec1.size() == vec2.size()); 或者在循环前检查,如果大小不同,抛出异常或处理错误。但用户的问题中没有提到这一点,可能默认假设两个vector大小相同。 综上,这个代码应该可以解决问题。同时,如果用户需要不同的差集方向(比如B-A),可以再创建一个循环来存储另一个方向的差集。 另外,用户可能希望将交集和差集的结果分别存入两个新的vector<set<int>>中,正如上面的代码所做的。 现在,根据用户提供的引用,特别是引用[3]中的例子,使用std::set_difference时参数的顺序决定了差集的方向。因此,用户如果希望得到A-B和B-A两种差集,需要分别调用两次,并存储到不同的vector中。但用户的问题中只提到差集,可能需要明确是哪种方向,但根据问题描述,可能只需要一个方向的差集。因此,在回答时需要说明这一点,或者给出示例代码处理一种或两种差集。 现在,我需要将上述思考整理成一个结构化的回答,确保符合用户的要求,包括使用正确的中文,代码格式正确,引用相关引用内容。 例如,在回答中可以提到使用std::set_intersection和std::set_difference函数,遍历vector的每个元素,使用std::inserter将结果插入到新set中,然后将这些set添加到结果vector中。同时,可以引用引用[3]中的内容,说明差集的方向由参数的顺序决定。 此外,引用[1]中提到的使用STL算法函数来处理集合操作,这里同样适用。所以,在回答中可以引用相关的引用内容,如引用[3]关于set_difference的参数顺序影响差集方向的说明。 最后,生成相关问题,可能涉及如何处理不同方向的差集,如何优化性能,或者处理vector大小不一致的情况等。</think>以下是实现两个$std::vector<std::set<int>>$容器对应位置集合的交集与差集的方法: ### 一、实现步骤 1. **参数校验**:确保两个$std::vector$长度相同,否则无法进行对应位置操作[^3] 2. **结果容器初始化**:创建两个新的$std::vector<std::set<int>>$容器存储结果 3. **遍历计算**:对每个位置的$std::set$元素执行以下操作: - **交集**:使用$std::set\_intersection$算法 - **差集**:使用$std::set\_difference$算法(参数顺序决定差集方向) ### 二、代码实现 ```cpp #include <vector> #include <set> #include <algorithm> #include <iterator> void compute_set_operations( const std::vector<std::set<int>>& vec1, const std::vector<std::set<int>>& vec2, std::vector<std::set<int>>& intersections, std::vector<std::set<int>>& differences_A_B) { assert(vec1.size() == vec2.size()); for (size_t i = 0; i < vec1.size(); ++i) { // 计算交集 std::set<int> intersect; std::set_intersection( vec1[i].begin(), vec1[i].end(), vec2[i].begin(), vec2[i].end(), std::inserter(intersect, intersect.begin())); // 计算差集(A-B) std::set<int> diff; std::set_difference( vec1[i].begin(), vec1[i].end(), vec2[i].begin(), vec2[i].end(), std::inserter(diff, diff.begin())); intersections.push_back(intersect); differences_A_B.push_back(diff); } } ``` ### 三、特性说明 1. **时间复杂度**:每个集合操作的时间复杂度为$O(n)$,其中$n$为集合元素数量[^1] 2. **容器特性**:$std::set$的自动排序特性确保了算法的高效执行 3. **扩展性**:修改参数顺序可计算不同方向的差集(如B-A)[^3] ### 四、使用示例 ```cpp std::vector<std::set<int>> vec1 = {{1,2,3}, {4,5,6}}; std::vector<std::set<int>> vec2 = {{2,3,4}, {4,5,7}}; std::vector<std::set<int>> intersections; std::vector<std::set<int>> diffs; compute_set_operations(vec1, vec2, intersections, diffs); /* 结果: intersections = {{2,3}, {4,5}} diffs = {{1}, {6}} */ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值