(自用)运算符重载 集合 交集和相对补集的错位问题

问题 D: 集合(运算符重载)

时间限制: 1 Sec  内存限制: 128 MB
提交: 187  解决: 109
[提交][状态][讨论版]

题目描述

集合是由一个或多个确定的元素所构成的整体。集合的运算有并、交、相对补等。

集合A和集合B的交集:由属于A且属于B的相同元素组成的集合。

集合A和集合B的并集:由所有属于集合A或属于集合B的元素所组成的集合。

集合B关于集合A的相对补集,记做A-B:由属于A而不属于B的元素组成的集合。

假设集合A={10,20,30},集合B={1,10,50,8}。则A与B的并是{10,20,30,1,50,8},A与B的交是{10},B关于A的相对补集是{20,30}。

定义整数集合类CSet,属性包括:集合中的元素个数n,整型指针data存储集合中的元素。

方法有:重载输出,按样例格式输出集合中的元素。

                      重载+运算符,求集合A和集合B的并集,并返回结果集合。

                     重载-运算符,求集合B关于集合A的相对补集,并返回结果集合。

                       重载*运算符,求集合A和集合B的交集,并返回结果集合。

主函数输入集合A、B的数据,计算集合的并、交、相对补。

可根据题目,为CSet类添加需要的成员函数。

                        

        

输入

 测试次数

每组测试数据两行,格式如下:

第一行:集合A的元素个数和元素

第二行:集合B的元素个数和元素

输出

 每组测试数据输出如下:

第一行:集合A

第二行:集合B

第三行:A和B的并

第四行:A和B的交

第五行:B关于A的相对补集 与 A关于B的相对补集的并,即(A-B)+(B-A)

每组测试数据间以空行分隔。

样例输入

2 3 10 20 30 4 10 1 2 3 5 100 2 3 4 -10 6 -34 12 2 4 90 100

样例输出

A:10 20 30 B:10 1 2 3 A+B:10 20 30 1 2 3 A*B:10 (A-B)+(B-A):20 30 1 2 3 A:100 2 3 4 -10 B:-34 12 2 4 90 100 A+B:100 2 3 4 -10 -34 12 90 A*B:100 2 4 (A-B)+(B-A):3 -10 -34 12 90

#include <iostream>
using namespace std;
class CSet {
	int n;
	int* data;
public:
	CSet(int n1 = 0, int* a = NULL) {
		n = n1;
		data = new int[n + 1];
		for (int i = 0; i < n; i++) {
			data[i] = a[i];
		}
	}
	friend ostream& operator<<(ostream& os, CSet& a) {
		for (int i = 0; i < a.n; i++) {
			os << a.data[i];
			if (i < a.n - 1)
				os << ' ';
			else if (i == a.n - 1)
				os << '\n';
		}
		return os;
	}
	friend CSet operator+(CSet& a, CSet&b) {
		int tn = b.n + a.n;
		int* temp = new int[tn + 1];
		int* temp2 = new int[tn + 1];
		for (int i = 0; i < tn; i++) {
			if (i < b.n)
				temp[i] = b.data[i];
			else if (i >=b.n)
				temp[i] = a.data[i - b.n];
		}
		temp2[0] = temp[0];
		int flag = 0;
		int ntemp = 0;
		for (int i = 0; i < tn; i++) {
			for (int j = 0; j < i; j++) {
				if (temp2[j] == temp[i]) {
					flag = 1;
				}
			}
			if (flag == 0) {
				temp2[i - ntemp] = temp[i];
			}
			else if (flag == 1) {
				ntemp++;
			}
			flag = 0;
		}
		CSet cs(tn - ntemp, temp2);
		return cs;
	}
	friend CSet operator * (CSet& a, CSet& b)
	{
		CSet c;
		int j, k, i = 0;
		int* p = new int[a.n];
		for (j = 0; j < a.n; j++)
		{
			for (k = 0; k < b.n; k++)
			{
				if (a.data[j] == b.data[k])
				{
					p[i] = a.data[j];
					i++;
					break;
				}
			}
		}
		c.data = new int[i];
		c.n = i;
		for (j = 0; j < i; j++)
		{
			c.data[j] = p[j];
		}

		delete[]p;
		return c;
	}
	friend CSet operator - (CSet& a, CSet& b)
	{
		CSet c;
		int i = 0, j, k, z;
		int* p = new int[a.n + b.n];
		for (j = 0; j < a.n; j++)
		{
			z = 0;
			for (k = 0; k < b.n; k++)
			{
				if (a.data[j] == b.data[k])
				{
					z = 0;
					break;
				}
				else
					z = 1;
			}
			if (z == 1)
			{
				p[i] = a.data[j];
				i++;
			}
		}
		c.n = i;
		c.data = new int[i];
		for (j = 0; j < i; j++)
		{
			c.data[j] = p[j];
		}
		delete[]p;
		return c;
	}
};
int main() {
	int t;
	cin >> t;
	while (t--) {
		int n, n2;
		cin >> n;
		int* a = new int[n + 1];
		for (int i = 0; i < n; i++)
			cin >> a[i];
		cin >> n2;
		int* a2 = new int[n2 + 1];
		for (int i = 0; i < n2; i++)
			cin >> a2[i];
		CSet A(n, a);
		CSet B(n2, a2);
		CSet C = A + B;
		CSet D = B - A;
		CSet E;
		cout << "A:" << A;
		cout << "B:" << B;
		cout << "A+B:" << C;
		C = A * B;
		cout << "A*B:" << C;
		C = A - B;
		E = C + D;
		//E = (A - B) + (B - A);
		cout << "(A-B)+(B-A):" << E<<endl;
		delete[]a;
		delete[]a2;
	}
}

重点在于交集和求相对补集时的错位,处理方法:

friend CSet operator * (CSet& a, CSet& b)
	{
		CSet c;
		int j, k, i = 0;
		int* p = new int[a.n];
		for (j = 0; j < a.n; j++)
		{
			for (k = 0; k < b.n; k++)
			{
				if (a.data[j] == b.data[k])
				{
					p[i] = a.data[j];
					i++;
					break;
				}
			}
		}
		c.data = new int[i];
		c.n = i;
		for (j = 0; j < i; j++)
		{
			c.data[j] = p[j];
		}

		delete[]p;
		return c;
	}
	friend CSet operator - (CSet& a, CSet& b)
	{
		CSet c;
		int i = 0, j, k, z;
		int* p = new int[a.n + b.n];
		for (j = 0; j < a.n; j++)
		{
			z = 0;
			for (k = 0; k < b.n; k++)
			{
				if (a.data[j] == b.data[k])
				{
					z = 0;
					break;
				}
				else
					z = 1;
			}
			if (z == 1)
			{
				p[i] = a.data[j];
				i++;
			}
		}
		c.n = i;
		c.data = new int[i];
		for (j = 0; j < i; j++)
		{
			c.data[j] = p[j];
		}
		delete[]p;
		return c;
	}
};

关键是所求得的补集和交集,数组下标的变量不要与循环体中变量一样,就可以很方便地错位了!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值