面向对象程序设计(基于C++)0601 自定义Set iSet.cpp

本文档展示了如何使用数组实现整数集合类iSet,包括并集、交集、差集和对称差集等操作,并提供单元测试以验证其功能。类iSet还包含了初始化、插入、删除、容量检查、打印、判断子集、包含检查等功能。代码中特别关注了赋值操作的正确性和内存管理,避免了潜在的数据丢失问题。
摘要由CSDN通过智能技术生成

要求

不能直接用STL,只能用数组,可以用algorithm的快排

至少包括:并集运算、交集运算、差集运算
其中s1 symmetric difference s2 = (s1 union s2) - (s1 intersect s2)
= (s1 - s2) union (s2 - s1)

对称的差集运算(S1和S2并 – S1和S2的交集) (s1 - s2) union (s2 - s1)
初始化 初值 initialization 参数不合理也要抛出异常
Assignment 赋值
Insert 插入
Erase 元素 没有就不改集合,不算异常
isSubset 判断是否为另一个集合的子集 返回bool
Contain 集合是否包含某个整数
Print 输出集合的值{}括起来,元素按顺序输出,逗号分隔
Size 元素多少 capacity 预留空间
isEmpty isFull 满的时候再加要产生异常
Clear 清除所有元素

个人实现iSet未详尽考虑到的点

①在实现operator=的时候没有考虑到class a; a = a;的时候会先释放掉a.ptr的内存再申请一块新的内存,这样会导致数据的丢失,因此如果a=a的情况下应该先对 传入的参数进行判定`this != &a

②依然是operator=,返回的类型应该返回引用值,虽然不返回引用值也是可行的,但是当无法进行链式编程,类似a = b = c的情况就无法实现,另外,如果只是值传递的话,会增加不必要的内存开销

③ 拷贝函数注意传入的参数也得用引用,如果不用引用的话,本身传入的参数是他的副本,副本又要拷贝一次类,这样会造成无限递归,导致栈溢出

测试代码

//----------------------------------------------------------------------
//
// Lab06Test.cpp : Test program for Lab 6.
//
//----------------------------------------------------------------------

#include <iostream>
using namespace std;

#include "iSet.h"  // your header file for class iSet

int main(int argc, char** argv)
try
  {
    // ***** test for initialization *****

    iSet s1{100};  // an integer set with 100 maximum elements
    iSet s2{110};   // an integer set with 110 maximum elements

    // ***** test for printing *****

    cout << "Set s1 after initialization: " << endl;
    s1.print();     // display set
    cout << endl;

    // ***** test for size *****

    cout << "The number of elements in Set s1: " << s1.size() << endl;
    cout << "The capacity of Set s1: " << s1.capacity() <<endl;

    cout << endl << "Set s2 after initialization: " << endl;
    s2.print();     // display set
    cout << endl;
    cout << "The number of elements in Set s2: " << s2.size() << endl;
    cout << "The capacity of Set s2: " << s2.capacity() << endl;
    cout << endl;

    // ***** test for inserting *****

    for (int i{200};i<220;i++)   s1.insert(i);        // insert 20 elements from 200 to 219
    for (int i{190};i<215;i++)   s2.insert(i);        // insert 25 elements from 190 to 214

    cout << "Set s1 after inserting: " << endl;
    s1.print();   // display set
    cout << endl;
    cout << "The number of elements in Set s1: " << s1.size() << endl;
    cout << "The capacity of Set s1: " << s1.capacity() << endl;
    cout << endl << "Set s2 after inserting: " << endl;
    s2.print();     // display set
    cout << endl;
    cout << "The number of elements in Set s2: " << s2.size() << endl;
    cout << "The capacity of Set s2: " << s2.capacity() << endl;
    cout << endl;

    // ***** test for union *****

    cout << "Union of two integer sets s1 and s2: " << endl;
    s1.print();     // display set
    cout << " 并 ";
    s2.print();    // display set
    cout << " = ";
    iSet r1{s1.setUnion(s2)};   // compute union of two integer sets
    r1.print();     // display union result
    cout << endl;
    cout << endl;

    // ***** test for intersection *****

    cout << "intersection of two integer sets s1 and s2: " << endl;
    s1.print();
    cout << " 交 ";
    s2.print();
    cout << " = ";
    iSet r2{s1.setIntsection(s2)};  // compute intersection of two integer sets
    r2.print();
    cout << endl;
    cout << endl;

    // ***** test for difference *****

    cout << "difference of two integer sets s1 and s2: " << endl;
    s1.print();
    cout << " 差 ";
    s2.print();
    cout << " = ";
    iSet r3{s1.setDifference(s2)};     // compute difference of two integer sets
    r3.print();
    cout << endl;
    cout << endl;

    cout << "difference of two integer sets s2 and s1: " << endl;
    s2.print();
    cout << " 差 ";
    s1.print();
    cout << " = ";
    iSet r4{s2.setDifference(s1)};     // compute difference of two integer sets
    r4.print();
    cout << endl;
    cout << endl;

    // ***** test for symmetric difference *****

    cout << "symmetric difference of two integer sets s1 and s2: " << endl;
    s1.print();
    cout << " symmetric差 ";
    s2.print();
    cout << " = ";
    iSet r5{s1.setSymmetricDifference(s2)};   // compute symmetric difference of two integer sets
    r5.print();
    cout << endl;
    cout << endl;

    // ***** test for assignment *****

    cout << "Set s1 after assignment s1=s2: " << endl;
    s1=s2;
    s1.print();
    cout << endl;
    cout << endl;

    // ***** test for "clear" *****

    cout << "Set s2 after erasing all elements: " << endl;
    s2.clear();
    s2.print();
    cout << endl;
    cout << endl;

    // ***** test for "isEmpty" *****

    if (s1.isEmpty()) cout << "Set s1 is empty " << endl;
    else cout << "Set s1 is NOT empty " << endl;
    cout << endl;

    if (s2.isEmpty()) cout << "Set s2 is empty " << endl;
    else cout << "Set s2 is NOT empty " << endl;
    cout << endl;

    // ***** test for "isFull" *****

    if (s1.isFull()) cout << "Set s1 is fully " << endl;
    else cout << "Set s1 is NOT full " << endl;
    cout << endl;

    if (s2.isFull()) cout << "Set s2 is full " << endl;
    else cout << "Set s2 is NOT full " << endl;
    cout << endl;

    // ***** test for "erase" *****

    cout << "Set s1 after erasing an element 211 : " << endl;
    s1.erase(211);
    s1.print();
    cout << endl;
    cout << endl;
    cout << "Set s1 after erasing an element 288 : " << endl;
    s1.erase(288);
    s1.print();
    cout << endl;
    cout << endl;

    // ***** test for "contains" *****
    int e{222};
    if (s1.contains(e)) cout << e << " is a member of s1" << endl;
    else cout << e << " is NOT a member of s1" << endl;
    cout << endl;
    e+=888;
    if (s1.contains(e)) cout << e << " is a member of s1" << endl;
    else cout << e << " is NOT a member of s1" << endl;
    cout << endl;


    // ***** test for "isSubset" *****

    if (s1.isSubset(s2)) cout << "Set s2 is a subset of s1" << endl;
    else cout << "Set s2 is NOT a subset of s1" << endl;
    cout << endl;

    cout << "Insert an element 888 into set s2 : " << endl;
    s2.insert(888);
    cout << "Set s2 : " << endl;
    s2.print();
    cout << endl;

    cout << endl;

    if (s1.isSubset(s2)) cout << "Set s2 is a subset of s1" << endl;
    else cout << "Set s2 is NOT a subset of s1" << endl;
    cout << endl;


    // ***** test for exception throwing *****

    cout << "insert 1000 elements from 1 to 999 into set s1 : " << endl;
    for (int i{1};i<1000;i++)
      s1.insert(i);        // insert 1000 elements from 1 to 999

    return 0;
  }

  // ***** exception handling *****

  catch(iSet::bad_iSet bi)  // catch exceptions related to integer set
  { switch (bi.errnum)          // # of exceptions
    { case 1: cerr << "bad iSet: constructor parameter<1 , exit " << endl;
			                    // error of constructor parameter
              break;
      case 2: cerr << "bad iSet: maximum elements reached(is Full), exit " << endl;
 		                                   // overflow of integer set
              break;
    }
    return 0;
  }

头文件代码(基本要求)

#pragma once
#include<iostream>
class iSet
{
private:
    int * ptr;
    int capability;
    int element;
    void uni_sort();
    

public:
    struct bad_iSet
    {
        int errnum;
    };
    iSet(int);
    iSet(const iSet &);
    ~iSet();
//基本要求
    int size()const;
    int capacity()const;
    void print()const;
    void insert(int);

    void erase(int);
    void clear();
    
    bool isEmpty()const;
    bool isFull()const;
    bool contains(int)const;
    bool isSubset(iSet&)const;

//注意用引用减少内存开销
    iSet setUnion(iSet&)const;
    iSet setIntsection(iSet&)const;
    iSet setDifference(iSet&)const;
    iSet setSymmetricDifference(iSet&)const;

//补充
    iSet& operator=(const iSet&);
    int find(int,int,int)const;
    
};

实现代码(基本要求)

#include"iSet.h"
#include<iostream>
#include<algorithm>

using namespace std;

int iSet::find(int num,int up,int low = 0)const
{
    if(up < low || up < 0 || low > element)
        return -1;
    
    int loc = (up + low) / 2;
    if(ptr[loc] == num)
        return loc;
    else if(ptr[loc] > num)
        return find(num,loc - 1, low);
    else if(ptr[loc] < num)
        return find(num,up, loc + 1);
}


iSet::iSet(int init_num)
{
    if(init_num < 1)
    {
        bad_iSet bi;
        bi.errnum = 1;
        throw bi;
    }
    ptr = new int[init_num];
    capability = init_num;
    element = 0;
    //初始化,申请内存,容量初始化,元素初始化
}
iSet::iSet(const iSet & S)
{
    this->ptr = new int[capability];
    this->capability = S.capability;
    this->element = S.element;
    for(int i = 0; i < S.element; i++)
        this->ptr[i] = S.ptr[i];
       
}
iSet::~iSet()
{
    delete[] ptr;//释放内存
}

int iSet::size()const
{
    return element;
}
int iSet::capacity()const
{
    return capability;
}
void iSet::print()const
{
    cout << '{';
    if(element > 0)
    {
        for(int i = 0; i < element - 1; i++)
            cout << ptr[i]<<",";
        cout << ptr[element - 1];
    }
    
    cout << '}';
}
void iSet::insert(int N)
{
    //要用二分查找
    if(capability == element)
    {
        bad_iSet bi;
        bi.errnum = 2;
        throw bi;
    }
    else if(element == 0)
    {
        ptr[element++] = N;
    }
    else if(find(N,element - 1) == -1)
    {
        ptr[element++] = N;
        sort(ptr, ptr + element);
    }
}

void iSet::erase(int N)
{
    int loc = find(N,element - 1);
    if(loc != -1 && loc < element)
    {
        ptr[loc] = ptr[--element];
        sort(ptr, ptr + element);
    }
    
}
void iSet::clear()
{
    element = 0;
}

bool iSet::isEmpty()const
{
    if(element == 0)
        return true;
    else
        return false;
}
bool iSet::isFull()const
{
    if(element == capability)
        return true;
    else
        return false;
}
bool iSet::contains(int N)const
{
    
    int loc = find(N,element - 1);
    if(loc != -1 && loc < element)
        return true;
    else return false;
}
bool iSet::isSubset(iSet &S)const
{
    if(this->element > S.element)
        return false;
    
    int bigloc = 0;
    for(int i = 0; i < this->element; i++)
    {
        //按顺序排好,所以从小到大查就好了
        for(int j = bigloc; j < S.element; j++)
        {
            if(this->ptr[i] == S.ptr[j])
                bigloc = j + 1;
            else if(this->ptr[i] < S.ptr[j])//this有一个数据小于S,而S后面的数据都大于this的这个数据,说明不包含
                return false;
        }
    }
    return true;
}

iSet iSet::setUnion(iSet& S)const    //并集
{
    iSet temp{S.capability + this->capability};
    for(int i = 0; i < S.element; i++)
    {
        temp.insert(S.ptr[i]);
    }
    for(int i = 0; i < this->element; i++)
    {
        temp.insert(this->ptr[i]);
    }
    return temp;
}
iSet iSet::setIntsection(iSet& S)const //交集
{
    iSet temp{((S.capability < this->capability) ? S.capability : this->capability)};
    for(int i = 0; i < this->element; i++)
    {
        // cout << ptr[i] << endl;
        // cout << S.find(this->ptr[i],S.element)<<endl;
        if(S.find(this->ptr[i],S.element) != -1)//注意是在THIS集合找S的数据
            temp.insert(this->ptr[i]);//找得到就插入,找不到不插入
    }
    return temp;
}
iSet iSet::setDifference(iSet& S)const //补集
{
    iSet temp{this->capability};
    for(int i = 0; i < this->element; i++)
        if(S.find(this->ptr[i],S.element) == -1)
            temp.insert(this->ptr[i]);
    return temp;

}
iSet iSet::setSymmetricDifference(iSet& S)const
{
    iSet s1{this->setUnion(S)};
    iSet s2{this->setIntsection(S)};
    iSet s3{s1.setDifference(s2)};
    return s3;
}

iSet& iSet::operator=(const iSet& S)
{
    //default copy错误
    if(this != &S)
    {
        delete[] ptr;
        ptr = new int[S.capability];
        this->element = S.element;
        this->capability = S.capability;
        for(int i = 0; i < S.capability; i++)
            this->ptr[i] = S.ptr[i];
    }
    
    return *this;
}

补充了一点STL的函数

zip下载
大致是这些内容

	iSet operator+(iSet&)const;//union并集
    iSet operator-(iSet&)const ;//dif差集
    iSet operator*(iSet&)const ;//inter交集
    iSet operator/(iSet&)const ;//sysmetric差
    friend ostream& operator<<(ostream&,const iSet);//输出内部所有数据
    friend istream& operator>>(istream&, iSet);//用>>运算符来插入数据
    int find(int,int,int)const;//二分查找
    int find(int)const;

    void resize(int);//更改容量大小
    
    int* begin()const;//return first element's point
    int* end()const;//return last element's+1 point
    int* upper_bound(int)const;//return element's point which is bigger than the num

更改日志

21-04-25 17:37 修正了重载运算符operator=在a = a这种情况下把内存释放掉导致数据缺失的情况

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值