定义并实现一个整数集合类int_set,集合类中cur_size表明当前集合中有几个整数,集合中最多含max_size个整数,存放集合元素的数组是动态的。要求提供的方法有:
(1) 增加一个整数到集合中;
(2)从集合中去掉一个元素;
(3)判断一个元素是否在集合中;
(4)重载<<运算法,输入集合;重载>>运算符输出集合;
(5)分别实现集合的交、并、差运算。
int_set.h :
#pragma once
#include<iostream>
using namespace std;
class int_set
{
private:
int cur_size;//实际长度
int max_size;//最大长度
int* num;
public:
int_set(int initialCapacity = 10);
int_set(const int_set&);
~int_set();
bool empty()const;
int size()const;
bool contain(int element)const;
int& get(int theIndex)const;
void add(int element);
void remove(int element);
void output()const;
friend istream& operator>>(istream&,int_set&);
friend ostream& operator<<(ostream&, const int_set&); void operator=(const int_set&);
int_set& operator=(int_set&);
int_set inter_set(int_set&);//求交集
int_set union_set(int_set&);//求并集
int_set differ_set(int_set&);//求差集
};
int_set.cpp :
#include "int_set.h"
int_set::int_set(int initialCapacity)
{
if (initialCapacity < 1) {
throw"集合长度要大于0\n";
}
max_size = initialCapacity;
num = new int[max_size];
cur_size = 0;
}
int_set::int_set(const int_set& set) {
max_size = set.max_size;
cur_size = set.cur_size;
num = new int[max_size];
copy(set.num, set.num + cur_size, num);
}
int_set::~int_set()
{
delete[]num;
}
bool int_set::empty() const
{
return cur_size == 0;
}
int int_set::size() const
{
return cur_size;
}
bool int_set::contain(int element) const
{
for (int i = 0;i < cur_size;i++) {
if (*(num + i) == element) {
return true;
}
}
return false;
}
int& int_set::get(int theIndex) const
{
if (theIndex < 0 || theIndex >= cur_size) {
throw "索引错误";
}
return *(num + theIndex);
}
void int_set::add(int element)
{
if (cur_size == max_size) {
throw"集合已满\n";
}
if (contain(element)) {
throw "集合已存在元素\n";
}
*(num + cur_size) = element;
cur_size++;
}
void int_set::remove(int element)
{
if (empty()) {
throw"集合为空\n";
}
if (!contain(element)) {
throw"该集合不存在该元素\n";
}
int* p = new int[max_size],n=0;
for (int i = 0;i < cur_size;i++) {
if (*(num + i) != element) {
*(p+n) = *(num + i);
n++;
}
}
delete[]num;
cur_size--;
num = p;
}
void int_set::output() const
{
for (int i = 0;i < cur_size;i++) {
cout << *(num + i)<<" ";
}
}
int_set& int_set::operator=(int_set&set)
{
if (this != &set) {
if (this != NULL)
delete[]num;
max_size = set.max_size;
cur_size = set.cur_size;
num = new int[max_size];
copy(set.num, set.num + cur_size, num);
}
return *this;
}
int_set int_set::inter_set(int_set& set)
{
int n = min(cur_size, set.cur_size);
int_set s(n);
for (int i = 0;i < cur_size;i++) {
if (set.contain(*(num + i))) {
s.add(*(num + i));
}
}
return s;
}
int_set int_set::union_set(int_set&set)
{
int n = cur_size + set.cur_size;
int_set s(n);
for (int i = 0;i < cur_size;i++) {
s.add(*(num + i));
}
for (int i = 0;i < set.cur_size;i++) {
if (!s.contain(*(set.num + i))) {
s.add(*(set.num + i));
}
}
return s;
}
int_set int_set::differ_set(int_set& set)
{
int_set s = inter_set(set);
int n = this->size() - s.size();
int_set differ(n);
for (int i = 0;i < cur_size;i++) {
if (!s.contain(*(num + i)) ){
differ.add(*(num + i));
}
}
return differ;
}
/*
有参构造函数初始化时,要保证最大长度大于0;
添加元素时,判断集合是否满
集合是否存在该元素
删除元素时,判读集合是否为空
集合是否不存在该元素
*/
istream& operator>>(istream&in, int_set& set)
{
int n, temp;
cout << "请输入集合长度:";
cin >> n;
while (n--) {
cout << "请输入要添加的元素:";
in >> temp;
set.add(temp);
}
return in;
}
ostream& operator<<(ostream& os, const int_set& set)
{
for (int i = 0;i < set.cur_size - 1;i++) {
os << *(set.num + i) << ",";
}
os << *(set.num + set.cur_size - 1);
return os;
}
Test.cpp :
#include<iostream>
using namespace std;
#include"int_set.h"
int main()
{
try {
int_set set1(-2);
}
catch ( const char* msg) {
cout << msg;
}
int_set set(5);
set.add(1);
set.add(3);
set.add(5);
set.add(7);
try {
set.add(5);
}
catch (const char* msg) {
cout << msg;
}
set.add(9);
try {
set.add(11);
}
catch (const char* msg) {
cout << msg;
}
//删除操作
try {
set.remove(23);
}
catch (const char* msg) {
cout << msg;
}
set.output();
cout << "\n";
set.remove(1);
set.remove(3);
set.remove(5);
set.remove(7);
set.remove(9);
try {
set.remove(5);
}
catch (const char* msg) {
cout << msg;
}
/*
理论上每一个add()、remove()都要用try、catch
这里我为了简便,只有异常情况使用了
*/
int_set s1,s2;
cin >> s1;
cout << "s1 = { ";
cout << s1<<"}\n";
cin >> s2;
cout << "s2 = { ";
cout << s2 << "}\n";
cout << "s1和s2的并集为:";
cout<<s1.union_set(s2)<<"\n";
cout << "s1和s2的交集为:";
cout << s1.inter_set(s2) << "\n";
cout << "s1和s2的差集为:";
cout << s1.differ_set(s2) << "\n";
return 0;
}
总结一下:今天遇到的问题困扰我很久,其实呢,当遇到指针时,要考虑重写复制构造函数和析构函数,还有重载赋值运算符。
在我写交集、并集和差集时,由于形参是类引用,不重写复制构造函数,就会导致申请的动态内存重复释放两次。