博文首先贴出交集、并集、差集、对称差运算的C++代码以及程序运行结果,然后再进行一个比较完整的构建代码思路解析,整个项目的实现功能如下:
文章目录
1. 实现代码以及程序运行结果
代码不太理解的,看下面解析。
1.1 头文件定义 UFSets.h
//该文章的原创作者:阿伟加油鸭。首发于CSDN平台,装载请标注博文出处。
//网址:https://blog.csdn.net/qq_45877524/article/details/106972508
/**
选择题目一:
结合离散数学中集合的性质于运算,设计集合类(元素的类型自行定义),并实现集合的基本运算,
包括:
……
**/
#ifndef UFSETS_H_
#define UFSETS_H_
#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>
#include<ostream>
using namespace std;
/**
UFSets类的设计思路:
用STL的容器vector以及algorithm库的算法来进行设计
**/
class UFSets {
private:
/**
用vector的原因:
1.vector自带智能指针,不需要进行特殊的删除,所以可以用默认析构函数
2.vector本身自带了许多检测函数比较方便
**/
vector<int> data;
public:
UFSets(); //构造函数,用来在空集上确定具体的元素
~UFSets(); //析构函数,这里用默认构造函数
bool isEmpty(); //确定是否为空集
bool isContain(int element) const; //确定是否包含某一个元素
bool isEquality( const UFSets& anotherSets); //判断两个集合是否相等
bool isSubSets(const UFSets& anotherSets); //判断是否为子集
void add(int element); //只是单纯的增加一个元素
void addElement(int element[], int length); //增加一组元素
void del(int element); //删除一个元素
UFSets unionSet(const UFSets& anotherSets); //并集操作
UFSets intersectSet(const UFSets& anotherSets); //交集操作
UFSets differenceSet(const UFSets& anotherSets); //差集操作
UFSets symDif(const UFSets& anotherSets); //全名:Symmetric difference,对称差运算
int getCount() const; //返回元素的个数
void Print() const; //打印当前的元素
};
#endif
1.2 抽象基类的实现 UFSets.cpp
//该文章的原创作者:阿伟加油鸭。首发于CSDN平台,装载请标注博文出处。
//网址:https://blog.csdn.net/qq_45877524/article/details/106972508
#include "UFSets.h"
//首先将vector容器设置为空
UFSets::UFSets()
{
data = { };
}
UFSets::~UFSets()
{
}
bool UFSets::isEmpty()
{
//bool std::vector<int>::empty() const 如果为空返回true,不为空为false
if (data.empty() == true)
return true;
else
return false;
}
bool UFSets::isContain(int element) const
{
//find函数用迭代器找元素,找的到就返回他在vector的位置,找不到就算球
if (find(data.begin(), data.end(), element) != data.end())
return true;
else
return false;
}
//其实该函数可以用vector自带的重载运算符==,来进行判断,但是打完才想起来算了
bool UFSets::isEquality(const UFSets& anotherSets)
{
if (data.size() != anotherSets.data.size()) { //连长度都不相等,肯定不相等
return false;
}
for (int i = 0; i < data.size(); i++) {
for(int j = 0;j < anotherSets.data.size();j++) //一个一个元素进行比较
if (data[i] != anotherSets.data[j])
return false;
}
return true;
}
//algorithm函数库中的includes函数来判断子集
bool UFSets::isSubSets(const UFSets& anotherSets)
{
return includes(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end());
}
//vector语法
void UFSets::add(int element)
{
data.push_back(element); //push_back函数为容器后面添加元素
}
//vector语法
void UFSets::addElement(int element[], int length)
{
for (int i = 0; i < length; i++)
add(element[i]); //一个一个往里面添加
sort(data.begin(),data.end());
}
void UFSets::del(int element)
{
if (isContain(element) == false) {
cout << "没有这个元素删除个蛇皮" << endl; //都不在删除个蛇蛇皮
return ;
}
auto location = find(data.begin(), data.end(), element); //找到特定元素,然后直接删除
data.erase(location);
}
/**
交、差、并、对称差运算都是用到了algorithm函数库中的函数
这四个函数的语法都是通用的:
以set_union为例:
set_union(data.begin(),data.end(),anotherSets.data.begin(),anotherSets.data.end(),
inserter(result.data,result.data.begin()));
前面四个参数都是vector的迭代器,最后一个参数是输出,那么这里在输出那里用inserter函数,将输出的
结果直接搞到vector容器中
**/
UFSets UFSets::unionSet(const UFSets& anotherSets)
{
UFSets result;
set_union(data.begin(),data.end(),anotherSets.data.begin(),anotherSets.data.end(),
inserter(result.data,result.data.begin()));
return result;
}
UFSets UFSets::intersectSet(const UFSets& anotherSets)
{
UFSets result;
set_intersection(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
UFSets UFSets::differenceSet(const UFSets& anotherSets)
{
UFSets result;
set_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
UFSets UFSets::symDif(const UFSets& anotherSets)
{
UFSets result;
set_symmetric_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
//元素的个数直接用vector的函数方法
int UFSets::getCount() const
{
return data.size();
}
//打印元素
void UFSets::Print() const
{
cout << "当前集合的元素" << endl;
for (int i = 0; i < data.size(); i++) {
cout << data[i] << " "<<endl;
}
cout << "完成" << endl;
}
1.3 测试函数以及测试用例 main.cpp
#include "UFSets.h"
/**
测试用例:
set1 = {1 3 5 7 9}
set2 = {2 4 6 7 9 10}
set2在删除元素2后的预测结果:
set2 = {4 6 7 9 10}
用set1进行属性测试函数的验证:
预期结果:
是否为空集 不是
是否包含元素1 是
是否与set2相等 不是
set1是否为set2的子集 不是
用set1和删除元素2以后的set2进行并,交,差,对称差运算的结果预测:
并集 1 3 4 5 6 7 9 10
交集 7 9
差集 1 3 5
对称差运算 1 3 4 5 6 10
**/
int main() {
int setOne[] = { 1,3,5,7,9 };
int setTwo[] = { 2,4,6,7,9,10 };
UFSets set1, set2;
set1.addElement(setOne, 5); //增加元素
set2.addElement(setTwo, 6); //增加元素
//打印这两个东西
set1.Print();
set2.Print();
//把2删除试一下
set2.del(2);
set2.Print();
//并,交,差,对称差运算
cout << "并集" << endl;
UFSets UnionSet = set1.unionSet(set2);
UnionSet.Print();
cout << "交集" << endl;
UFSets IntersectSet = set1.intersectSet(set2);
IntersectSet.Print();
cout << "差集" << endl;
UFSets DifferenceSet = set1.differenceSet(set2);
DifferenceSet.Print();
cout << "对称差运算" << endl;
UFSets symdif = set1.symDif(set2);
symdif.Print();
//返回set1的元素个数
cout << "接下来都是set1的验证" << endl;
cout << set1.getCount() << endl;
cout << "是否为空集" << " "<<set1.isEmpty() << endl;
cout << "是否包含元素" <<" " <<set1.isContain(1) << endl;
cout << "是否相等" <<" "<< set1.isEquality(set2) << endl;
cout << "set1是否为set2的子集" <<" "<< set1.isSubSets(set2) << endl;
return 0;
}
1.4 代码运行结果
1.5 代码环境
C++11,运行不成功可能是dev版本过老的问题,反正我用dev和visual stduio 2020都是没有问题的。
2 代码构建思路
我的代码构建思路可能不太成熟,望大佬指正。
设计一个类,首先应该考虑的是用什么东西来存储相应的元素,那么对于设计的需求而言,我要做的是元素(单个数据)与元素(单个数据)之间的交互。所以有两个选择,一个是数组,那么另外一个STL容器的vector(vector容器比较常用,相当于数组的2.0版本)
考虑到下面两个原因,我选择vector容器:
- 在algorithm中本身就有差集、交集、并集和对称差运算的标准函数。它们的用法如下(看不懂的,看下面文章链接,里面有迭代器、vector容器、algorithm的介绍):
- vector容器可以进行自我检测,empty之类都有,可以非常方便的运算减少
当然,在交集、并集、差集、对称差运算这三个学校所谓必须要掌握,实际没个der的程序中,我也会用数组的方法,进行解释。
这是STL的介绍补充以及vector容器的用法:
- CSDN博主禾夕的《STL vector的内部实现原理及基本用法》
- CSDN博主boke_fengwei的《c+±–vector的使用》
- CSDN博主yyce的《面向对象程序设计(C++) 示例程序——集合类》
- CSDN博主 HUST_Miao的《C++中STL用法超详细总结》
3. 交集、并集、差集、对称差运算
有两种方法进行实现:一种是用到了algorithm函数库里面的函数,一种是直接头铁来弄。
3.1 运用到了algorithm函数库里面的函数
其实我这个程序,已经用到了algorithm函数库里面的函数,下面对着来讲一下:
扫描二维码关注公众号,回复:
11398871 查看本文章
![](/qrcode.jpg)
UFSets UFSets::unionSet(const UFSets& anotherSets)
{
UFSets result;
set_union(data.begin(),data.end(),anotherSets.data.begin(),anotherSets.data.end(),
inserter(result.data,result.data.begin()));
return result;
}
UFSets UFSets::intersectSet(const UFSets& anotherSets)
{
UFSets result;
set_intersection(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
UFSets UFSets::differenceSet(const UFSets& anotherSets)
{
UFSets result;
set_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
UFSets UFSets::symDif(const UFSets& anotherSets)
{
UFSets result;
set_symmetric_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
那么好,对其中起主要作用的四个函数进行分析
//并集
set_union(data.begin(),data.end(),anotherSets.data.begin(),anotherSets.data.end(),
inserter(result.data,result.data.begin()));
//交集
set_intersection(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
//差集
set_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
//对称差运算
set_symmetric_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
这四个函数的注意事项以及调用方式都是一样,那么以std::set_difference为例,先说函数的调用方式,再说注意事项。
调用方式:
template<class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator set_difference(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result)
InputIterator = 输入数组的迭代器 OutputIterator = 输出迭代器
示例:
UFSets UFSets::differenceSet(const UFSets& anotherSets)
{
UFSets result;
set_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),
inserter(result.data, result.data.begin()));
return result;
}
InputIterator输入数组迭代器,直接像我这样用,这个比较明白
在调用方式这里,OutputIterator可能有点蒙,我这里推荐用inserter:
inserter(container,pos):返回通用插入型迭代器,内部会调用容器container的insert(pos)方法将数据插入到pos位置。
用法通俗一点:
inserter(你现在用的函数,你要插入的位置)
你可以用ostream但是比较复杂一点,按着例子来吧:
set_difference(data.begin(), data.end(), anotherSets.data.begin(), anotherSets.data.end(),ostream_iterator<int>(cout," "));
set_differene虽然头上带着一个set,而是一个通用函数,STL容器(除了个别容器)有手就行,但是有个条件,传递的容器必须是排序的。因此,我在addElement函数那里加了一个sort把他搞有序了:
//vector语法
void UFSets::addElement(int element[], int length)
{
for (int i = 0; i < length; i++)
add(element[i]); //一个一个往里面添加
sort(data.begin(),data.end());
}
四个函数非常具体的分析包括底层实现看这里:
- CSDN博主Sim0Hayha的《【C++】关于 std::set_intersection( ) 函数用法》
- CSDN博主清远qingyuan的《C++集合操作之集合差集:std::set_difference》
- CSDN博主清远qingyuan的《C++集合操作之集合并集:std::set_union》
- CSDN博主星辰浩宇的《关于C++中使用set_union、set_intersection、set_difference,set_symmetric_difference、merge的总结》
3.2 直接用数组
篇幅有限,看这里:CSDN博主tx何家科03的《输入两个集合求出它们的交集,并集,相对差与相对补集并判断他们是否相等》
4. 参考资料
- CSDN博主Sim0Hayha的《【C++】关于 std::set_intersection( ) 函数用法》
- CSDN博主禾夕的《STL vector的内部实现原理及基本用法》
- CSDN博主boke_fengwei的《c+±–vector的使用》
- CSDN博主yyce的《面向对象程序设计(C++) 示例程序——集合类》
- CSDN博主 HUST_Miao的《C++中STL用法超详细总结》
- CSDN博主清远qingyuan的《C++集合操作之集合差集:std::set_difference》