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

问题 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;
	}
};

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你解决这个问题。以下是使用C语言计算两个集合的并交集、差的代码: ```c #include <stdio.h> #define MAX_SIZE 100 void input_set(int set[], int *size); void print_set(int set[], int size); void intersection(int set1[], int size1, int set2[], int size2, int result[], int *size); void union_set(int set1[], int size1, int set2[], int size2, int result[], int *size); void difference(int set1[], int size1, int set2[], int size2, int result[], int *size); int main() { int set1[MAX_SIZE], set2[MAX_SIZE], result[MAX_SIZE]; int size1, size2, result_size; printf("请输入第一个集合:\n"); input_set(set1, &size1); printf("请输入第二个集合:\n"); input_set(set2, &size2); printf("第一个集合为:\n"); print_set(set1, size1); printf("第二个集合为:\n"); print_set(set2, size2); // 计算并 union_set(set1, size1, set2, size2, result, &result_size); printf("两个集合的并为:\n"); print_set(result, result_size); // 计算交集 intersection(set1, size1, set2, size2, result, &result_size); printf("两个集合交集为:\n"); print_set(result, result_size); // 计算差 difference(set1, size1, set2, size2, result, &result_size); printf("两个集合的差为:\n"); print_set(result, result_size); return 0; } // 输入集合 void input_set(int set[], int *size) { printf("请输入集合元素的数量:"); scanf("%d", size); printf("请输入集合元素:\n"); for (int i = 0; i < *size; ++i) { scanf("%d", &set[i]); } } // 输出集合 void print_set(int set[], int size) { printf("{"); for (int i = 0; i < size; ++i) { printf("%d", set[i]); if (i != size - 1) { printf(", "); } } printf("}\n"); } // 计算两个集合交集 void intersection(int set1[], int size1, int set2[], int size2, int result[], int *size) { *size = 0; for (int i = 0; i < size1; ++i) { for (int j = 0; j < size2; ++j) { if (set1[i] == set2[j]) { result[*size] = set1[i]; ++(*size); break; } } } } // 计算两个集合的并 void union_set(int set1[], int size1, int set2[], int size2, int result[], int *size) { *size = 0; for (int i = 0; i < size1; ++i) { result[*size] = set1[i]; ++(*size); } for (int i = 0; i < size2; ++i) { int found = 0; for (int j = 0; j < size1; ++j) { if (set2[i] == set1[j]) { found = 1; break; } } if (!found) { result[*size] = set2[i]; ++(*size); } } } // 计算两个集合的差 void difference(int set1[], int size1, int set2[], int size2, int result[], int *size) { *size = 0; for (int i = 0; i < size1; ++i) { int found = 0; for (int j = 0; j < size2; ++j) { if (set1[i] == set2[j]) { found = 1; break; } } if (!found) { result[*size] = set1[i]; ++(*size); } } } ``` 这段代码中,我们定义了4个函数:`input_set`用于输入集合,`print_set`用于输出集合,`union_set`计算两个集合的并,`intersection`计算两个集合交集,`difference`计算两个集合的差。在主函数中,我们首先输入两个集合,然后分别计算它们的并交集、差,并输出结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值