问题 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;
}
};
关键是所求得的补集和交集,数组下标的变量不要与循环体中变量一样,就可以很方便地错位了!!!