关于c++ 集合类的综合运用

img

img


如图所示,题目要求实现类的综合运用,包括集合的交,差,并等等

Set中不存在重复元素,插入的时候需要遍历进行判断。
代码如下:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class AbsCollection{
protected:
    int* iPtr;        //指向数组的指针
    int last;        //数组最后一个元素的位置
    int maxSize;    //数组总体长度
public:
    AbsCollection(int size = 100) {
        maxSize = size;
        iPtr = new int[maxSize];
        last = -1;
    };
    virtual ~AbsCollection() {
        if (iPtr != 0) {
            delete[] iPtr;
            iPtr = 0;
        }
    }
    void OutputSet()  { //输出集合中元素
        for (int i = 0; i <= last; i++)
            cout << iPtr[i] << " ";
        cout << endl;
    }
};
class Set :public AbsCollection
{
private:
    char* fileName; //存放数据的文件
public:
    Set(int size = 100, const char* szFileName = "");//从文件读取数据存入数组(要判断是否有重复元素)
    virtual ~Set();        //析构函数,释放内存并将数据写入文件
    void input(int x);
    void erase(int x);
    int isInSet(int x);     //判断x是否已经存在于集合中
    friend ostream& operator<<(ostream& os, Set& s);
    void intersetion(Set& s);//求集合的交(*this与s的交,结果放在*this中)
    void operator+(Set& s);     //求集合的并(*this与s的并,结果放在*this中)
    void diff(Set& s);         //求集合的差(*this与s的差,结果放在*this中)
    Set& operator=(Set& s);  //赋值拷贝函数
    void sort();             //将集合中元素从大到小排序

    void setFile(const char* file) { //设置文件函数,避免多个对象在析构时写入一个文件(通过=或者使用默认参数构建对象时会出现这个问题)
        fileName = const_cast<char*>(file);
    }
};

Set::Set(int size, const char* szFileName):AbsCollection(size)
{
    try
    {
        if (size < 1)
            throw - 1; //抛出异常

        fileName = const_cast<char*>(szFileName);
        if (strlen(fileName) == 0)
            return;
        ifstream is(fileName);
        if (is.is_open())
        {
            int t;
            while (!is.eof())
            {
                is >> t;
                //判断数据是否已经存在,过滤掉重复元素
                int k = 0;
                for (; k <= last; k++)
                {
                    if (iPtr[k] == t)
                        break;
                }
                if (k > last) //没有重复数字
                {
                    last++;
                    iPtr[last] = t;
                }

            }
            is.close();
        }
    }
    catch (int ) //捕获异常输出提示
    {
        cout << "Invalid Argument: size<10" << endl;
    }
}
Set::~Set()
{
    ofstream os(fileName); //数据写入文件
    os << endl;
    for (int i = 0; i <= last; i++)
        os << iPtr[i] << " ";
    os << endl;
    os.close();
}
void Set::input(int x) //insert还是input?
{
    if (last == maxSize - 1)
    {
        cout << "集合已满,插入失败!" << endl;
        return;
    }
    if (!isInSet(x))
    {
        last++;
        iPtr[last] = x;
        cout << "插入成功!" << endl;
    }
    else
        cout << x << "已在集合中,插入失败!" << endl;
}

void Set::erase(int x)
{
    int flag = 0;
    for (int i = 0; i <= last; i++)
    {
        if (iPtr[i] == x)
        {
            for (int j = i; j < last; j++)
                iPtr[j] = iPtr[j + 1];
            last--;
            flag = 1;
            cout << "删除成功!" << endl;
            break;
        }
    }
    if (flag == 0)
        cout << x << "不再集合中,删除失败!" << endl;
}
int Set::isInSet(int x)
{
    for (int i = 0; i <= last; i++)
    {
        if (iPtr[i] == x)
        {
            return 1;
        }
    }
    return 0;
}
ostream& operator<<(ostream& os, Set& s)
{
    for (int i = 0; i <= s.last; i++)
        os << s.iPtr[i] << " ";

    return os;
}
void Set::intersetion(Set& s)//求集合的交(*this与s的交,结果放在*this中)
{
    int i = 0, j = 0;
    for (; i <= last; i++)
    {
        if (s.isInSet(iPtr[i])) //同时在*this和s中
        {
            iPtr[j++] = iPtr[i];
        }
    }
    last = j - 1;
}

void Set::operator+(Set& s)     //求集合的并(*this与s的并,结果放在*this中)
{
    for (int i = 0; i <= s.last; i++)
    {
        if (!isInSet(s.iPtr[i])) //s中的元素不再*this中,则插入*this中
        {
            if (last < maxSize-1)
            {
                last++;
                iPtr[last] = s.iPtr[i];
            }
            else
                cout << "集合已满,插入失败!" << endl;
        }
    }
}

void Set::diff(Set& s)         //求集合的差(*this与s的差,结果放在*this中)
{
    //删除*this中与s中相同的
    int t = last;
    for (int i = 0; i <= last; i++)
    {
        if (s.isInSet(iPtr[i]))
        {
            for (int j = i; j < last; j++)
                iPtr[j] = iPtr[j + 1];
            last--;
            i--; //因为删除后,所有数据都前移1位,这里为了抵消for循环的i++
        }
    }
}

Set& Set::operator=(Set& s)  //赋值拷贝函数
{
    delete[] iPtr;
    maxSize = s.maxSize;
    fileName = const_cast<char*>(s.fileName);
    iPtr = new int[maxSize];
    for (int i = 0; i <= s.last; i++)
        iPtr[i] = s.iPtr[i];
    last = s.last;
    return *this;
}
void Set::sort()             //将集合中元素从大到小排序
{
    int t;
    for (int i = 0; i < last; i++)
    {
        for (int j = 0; j < last - i; j++)
        {
            if (iPtr[j] < iPtr[j + 1])
            {
                t = iPtr[j];
                iPtr[j] = iPtr[j + 1];
                iPtr[j + 1] = t;
            }
        }
    }
}


int main()
{
    Set s1(20, "f1.txt");
    cout << "从f1.txt中读取数据构建Set对象s1,对象内容为:" << endl;
    s1.OutputSet();

    //插入数据
    int x;
    cout << "请输入要插入的数据:";
    cin >> x;
    s1.input(x);
    

    //删除
    cout << "请输入要删除的数据:";
    cin >> x;
    s1.erase(x);

    //是否在集合中
    cout << "请输入一个数x,判断x是否在集合中:";
    cin >> x;
    if (s1.isInSet(x))
        cout << x << "在集合s1中" << endl;
    else
        cout << x << "不在集合s1中" << endl;

    cout << endl << "操作完成后,s1中的内容为:" ;
    cout << s1 << endl;


    //构建集合对象s2
    cout << "从f2.txt读取数据构建集合对象s2:" << endl;
    Set s2(20,"f2.txt");
    cout << "集合对象s2中的数据元素为:";
    cout << s2 << endl; //或者     s2.OutputSet();

    //使用=复制s1,以便计算交集、并集和差集
    Set s3(20), s4(20);
    s3 = s1;
    s4 = s1;
    s3.setFile("f3.txt");
    s4.setFile("f4.txt");

    cout << "使用=复制s1,构建集合对象s3、s4" << endl << endl;
    //s1与s2的交集
    cout <<"s1: "<< s1 << endl;
    cout <<"s2: "<< s2 << endl;
    s1.intersetion(s2);
    cout << "s1与s2的交集:" << endl;
    cout << s1 << endl;

    //s3与s2的并集
    cout << endl << endl;
    cout << "s3: " << s3 << endl;
    cout << "s2: " << s2 << endl;
    s3 + s2; //+的返回值是void类型,结果保存到+前面的对象中,所以这里不能用=来保存结果
    cout << "s3与s2的并集:" << endl;
    cout << s3 << endl;

    //s4与s2的差集
    cout << endl << endl;
    cout << "s4: " << s4 << endl;
    cout << "s2: " << s2 << endl;
    cout << "s4与s2的差集:" << endl;
    s4.diff(s2);
    cout << s4 << endl;

    cout << endl << "集合s4的内容:" << endl;
    cout << s4 << endl;
    cout << "集合s4排序后:" << endl;
    s4.sort();
    cout << s4 << endl;

    return 0;
    //程序结束后调用s1-s4的析构函数,将结果写入文件
}

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7674362
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:C++输入一个数,将其插入到一维数组合适的位置,插入后的数组依然有序
  • 除此之外, 这篇博客: c++类的对象与使用、类的构造函数、类的组合中的 类定义的正式语法形式如下: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • class 类名称
    {
    public:
        外部成员
    protected:
        保护型成员
    private:
        私有成员
    };
    

    其中,public,protected和private都是对类成员的不同访问权限控制

    类的成员函数定义必须写在类内

  • 您还可以看一下 王健伟老师的C++语言基础到进阶课程中的 类型转换构造函数、运算符,类成员指针小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    我可以给您提供一些关于如何使用c++实现集合的综合运用的建议。

    在C++中,可以通过各种数据结构实现集合。具体而言,可以使用数组、链表、栈、队列等。其中,数组的查询速度很快,但是插入和删除速度较慢;链表的插入和删除速度很快,但是查询速度较慢;栈和队列则可以通过不同的方式来实现集合操作。

    在实现集合的综合运用中,主要需要实现以下几个操作:

    1. 初始化集合

    可以使用数组、链表等数据结构来存储集合中的元素。初始化集合时,需要定义一个数组或链表,并将所有元素插入到其中。

    例如,使用数组来实现一个集合:

    #include <iostream>
    using namespace std;
    const int MAX_SIZE = 100;
    class Set {
    private:
        int elements[MAX_SIZE];
        int size;
    public:
        Set() {
            size = 0;
        }
        void add(int x) {
            elements[size++] = x;
        }
        void output() {
            for (int i = 0; i < size; i++) {
                cout << elements[i] << " ";
            }
            cout << endl;
        }
    };
    int main() {
        Set set;
        set.add(1);
        set.add(2);
        set.add(3);
        set.output();
        return 0;
    }
    
    1. 集合的交集

    可以使用双指针法来实现两个有序集合的交集。具体而言,定义两个指针i和j,并将它们分别指向两个集合的开头。如果第一个集合的元素小于第二个集合的元素,则将指针i向后移动一位;如果第二个集合的元素小于第一个集合的元素,则将指针j向后移动一位;如果两个集合的元素相等,则将该元素加入到交集中,并将指针i和j都向后移动一位。

    例如,实现两个有序集合的交集:

    #include <iostream>
    using namespace std;
    const int MAX_SIZE = 100;
    class Set {
    private:
        int elements[MAX_SIZE];
        int size;
    public:
        Set() {
            size = 0;
        }
        void add(int x) {
            elements[size++] = x;
        }
        void output() {
            for (int i = 0; i < size; i++) {
                cout << elements[i] << " ";
            }
            cout << endl;
        }
        Set intersect(Set& other) {
            Set result;
            int i = 0;
            int j = 0;
            while (i < size && j < other.size) {
                if (elements[i] < other.elements[j]) {
                    i++;
                }
                else if (other.elements[j] < elements[i]) {
                    j++;
                }
                else {
                    result.add(elements[i]);
                    i++;
                    j++;
                }
            }
            return result;
        }
    };
    int main() {
        Set set1;
        set1.add(1);
        set1.add(2);
        set1.add(3);
        Set set2;
        set2.add(2);
        set2.add(3);
        set2.add(4);
        Set result = set1.intersect(set2);
        result.output();
        return 0;
    }
    
    1. 集合的并集

    可以使用哈希表来实现两个集合的并集。具体而言,将两个集合中的元素哈希到一个哈希表中,然后输出哈希表中的所有元素。

    例如,实现两个集合的并集:

    #include <iostream>
    #include <unordered_set>
    using namespace std;
    const int MAX_SIZE = 100;
    class Set {
    private:
        int elements[MAX_SIZE];
        int size;
    public:
        Set() {
            size = 0;
        }
        void add(int x) {
            elements[size++] = x;
        }
        void output() {
            for (int i = 0; i < size; i++) {
                cout << elements[i] << " ";
            }
            cout << endl;
        }
        unordered_set<int> get_set() {
            unordered_set<int> result;
            for (int i = 0; i < size; i++) {
                result.insert(elements[i]);
            }
            return result;
        }
    };
    int main() {
        Set set1;
        set1.add(1);
        set1.add(2);
        set1.add(3);
        Set set2;
        set2.add(3);
        set2.add(4);
        set2.add(5);
        unordered_set<int> result_set;
        unordered_set<int> set1_set = set1.get_set();
        for (int i = 0; i < set1.size; i++) {
            result_set.insert(set1.elements[i]);
        }
        for (int i = 0; i < set2.size; i++) {
            if (set1_set.count(set2.elements[i]) == 0) {
                result_set.insert(set2.elements[i]);
            }
        }
        for (int x : result_set) {
            cout << x << " ";
        }
        cout << endl;
        return 0;
    }
    
    1. 集合的差集

    集合的差集可以通过对原始集合进行一些操作来实现。例如,可以将第一个集合中不属于第二个集合的元素添加到新的集合中。

    例如,实现两个集合的差集:

    #include <iostream>
    #include <unordered_set>
    using namespace std;
    const int MAX_SIZE = 100;
    class Set {
    private:
        int elements[MAX_SIZE];
        int size;
    public:
        Set() {
            size = 0;
        }
        void add(int x) {
            elements[size++] = x;
        }
        void output() {
            for (int i = 0; i < size; i++) {
                cout << elements[i] << " ";
            }
            cout << endl;
        }
        unordered_set<int> get_set() {
            unordered_set<int> result;
            for (int i = 0; i < size; i++) {
                result.insert(elements[i]);
            }
            return result;
        }
    };
    int main() {
        Set set1;
        set1.add(1);
        set1.add(2);
        set1.add(3);
        Set set2;
        set2.add(3);
        set2.add(4);
        set2.add(5);
        unordered_set<int> set1_set = set1.get_set();
        unordered_set<int> set2_set = set2.get_set();
        unordered_set<int> result_set;
        for (int x : set1_set) {
            if (set2_set.count(x) == 0) {
                result_set.insert(x);
            }
        }
        for (int x : result_set) {
            cout << x << " ";
        }
        cout << endl;
        return 0;
    }
    

    希望上述建议可以对您有所帮助。

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632