交集、并集、差集、对称差运算(集合类) C++实现

博文首先贴出交集、并集、差集、对称差运算的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容器:

  1. 在algorithm中本身就有差集、交集、并集和对称差运算的标准函数。它们的用法如下(看不懂的,看下面文章链接,里面有迭代器、vector容器、algorithm的介绍):
  2. vector容器可以进行自我检测,empty之类都有,可以非常方便的运算减少
    当然,在交集、并集、差集、对称差运算这三个学校所谓必须要掌握,实际没个der的程序中,我也会用数组的方法,进行解释。

这是STL的介绍补充以及vector容器的用法:

  1. CSDN博主禾夕的《STL vector的内部实现原理及基本用法
  2. CSDN博主boke_fengwei的《c+±–vector的使用
  3. CSDN博主yyce的《面向对象程序设计(C++) 示例程序——集合类
  4. CSDN博主 HUST_Miao的《C++中STL用法超详细总结

3. 交集、并集、差集、对称差运算

有两种方法进行实现:一种是用到了algorithm函数库里面的函数,一种是直接头铁来弄。

3.1 运用到了algorithm函数库里面的函数

其实我这个程序,已经用到了algorithm函数库里面的函数,下面对着来讲一下:

扫描二维码关注公众号,回复: 11398871 查看本文章
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());
}

四个函数非常具体的分析包括底层实现看这里:

  1. CSDN博主Sim0Hayha的《【C++】关于 std::set_intersection( ) 函数用法
  2. CSDN博主清远qingyuan的《C++集合操作之集合差集:std::set_difference
  3. CSDN博主清远qingyuan的《C++集合操作之集合并集:std::set_union
  4. CSDN博主星辰浩宇的《关于C++中使用set_union、set_intersection、set_difference,set_symmetric_difference、merge的总结

3.2 直接用数组

篇幅有限,看这里:CSDN博主tx何家科03的《输入两个集合求出它们的交集,并集,相对差与相对补集并判断他们是否相等

4. 参考资料

  1. CSDN博主Sim0Hayha的《【C++】关于 std::set_intersection( ) 函数用法
  2. CSDN博主禾夕的《STL vector的内部实现原理及基本用法
  3. CSDN博主boke_fengwei的《c+±–vector的使用
  4. CSDN博主yyce的《面向对象程序设计(C++) 示例程序——集合类
  5. CSDN博主 HUST_Miao的《C++中STL用法超详细总结
  6. CSDN博主清远qingyuan的《C++集合操作之集合差集:std::set_difference

猜你喜欢

转载自blog.csdn.net/qq_45877524/article/details/106972508