检查数组是否是另一个数组的子集? (C ++)

时间:2016-11-29 08:54:41

标签: c++ arrays

理想的想法是:输入一套尺寸&成员,如果大小有效,则输入第一个子集(A),如果A是有效子集,则对第二个子集(B)执行相同操作。

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
    while (true) {
        int i = 0;
        int k = 0;
        int * set;
        int setSize;
        cout << "Input size of set" << endl;
        cin >> setSize;
        if (setSize <= 0) {
            cout << "Invalid size!" << endl;
        }
        else {
            set = new int[setSize];
            for (int i = 0; i < setSize; i++)
            {
                cout << "set[" << i + 1 << "]=";
                cin >> set[i];
            }
            int * A;
            int sizeA;
            cout << "Input size of subset A" << endl;
            cin >> sizeA;
            if (sizeA <= 0 || sizeA > setSize) {
                cout << "Invalid size for a subset, please try again!" << endl;
            }
            else {
                A = new int[sizeA];
                cout << "Input members of A" << endl;
                for (int i = 0; i < sizeA; i++)
                {
                    cout << "A[" << i + 1 << "]=";
                    cin >> A[i];
                }
                for (i = 0; i < sizeA; i++)
                {
                    for (k = 0; k < setSize; k++)
                    {
                        if (A[i] == set[k])
                            break;
                    }
                    if (k == setSize) {
                        return 0;
                    }
                    else{
                        int * B;
                        int sizeB;
                        cout << "Input size of subset B" << endl;
                        cin >> sizeB;
                        if (sizeB <= 0 || sizeB > setSize) {
                            cout << "Invalid size for a subset, please try again!" << endl;
                        }
                        else {
                            B = new int[sizeB];
                            cout << "Input members of B" << endl;
                            for (int i = 0; i < sizeB; i++)
                            {
                                cout << "B[" << i + 1 << "]=";
                                cin >> B[i];
                            }
                            for (i = 0; i < sizeB; i++)
                            {
                                for (k = 0; k < setSize; k++)
                                {
                                    if (B[i] == set[k])
                                        break;
                                }
                                if (k == setSize) {
                                    cout << "Not a subset, please try again!" << endl;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

然后我想将&#em; em转换为位串并执行一些操作...

1 个答案:

答案 0 :(得分:1)

我会提供一些关于如何处理编程问题的建议,而不是用勺子提供完整的答案。

首先,不要在main()中写下所有内容。相反,声明一个对合适的数据结构进行操作并返回适当结果的函数。对于这个函数,很明显结果应该是bool - 如果第二个数组是第一个数组的子集,则为true,否则为false:

bool is_subset(std::vector<int> a, std::vector<int> b);

我选择了vector,因为它随身携带它的大小,使其更容易使用。

现在我们有了,我们可以开始测试它了(是的,我们首先编写测试 - 显然它们会失败直到我们实现is_subset(),但这就是我们知道测试是否有用的方法)。我能想到的最简单的测试是,“空集是其自身的一个子集吗?”:

int main()
{
    assert(is_subset({}, {}));
}

为此测试编写足够的代码以通过。它可以像

一样简单
bool is_subset(std::vector<int> a, std::vector<int> b)
{
    return a == b;
}

这显然不完整,但没关系。它足以满足我们到目前为止的测试,但我们需要添加更多测试。所以,继续写另一个测试:

int main()
{
    // empty set is a subset of itself
    assert(is_subset({}, {}));

    // empty set is a subset of a non-empty set
    assert(is_subset({1}, {}));
}

让它通过:

bool is_subset(std::vector<int> a, std::vector<int> b)
{
    using std::begin;
    using std::end;

    return std::includes(begin(a), end(a),  begin(b), end(b));
}

还有一些基本的测试 - 例如,一个简单的集合总是它自身的一个子集,例如,没有非空集合是空集合的子集。

然后,您可以开始通过测试获得更多创意。随着测试列表的增长,您正在构建一个对函数所需要的描述,这比您的自然语言散文更清晰(例如,'set'是什么意思?它可以重复元素吗?)。

一旦你有了一个有效的测试函数,你就可以添加输入(来自stdin,或来自命令参数)和输出(到stdout,或作为退出代码)的细节。请注意,我已经展示了几种输入和输出方式 - 使用单独的功能,您可以根据需要将不同的I / O功能与您的算法混合搭配。

您还可以查看进一步的改进,例如使用模板,以便您可以使用longstd::string等类型代替int(但请确保您知道在尝试doublefloat之前,浮点相等的问题。

一旦我实施了一些测试,这就是我的完整程序的样子:

#include <cassert>
#include <algorithm>
#include <vector>

bool is_subset(std::vector<int> a, std::vector<int> b);

int main()
{
    // empty set is a subset of itself
    assert(is_subset({}, {}));

    // empty set is a subset of a non-empty set
    assert(is_subset({1}, {}));

    // no non-empty set is a subset of an empty set
    assert(!is_subset({}, {1}));

    // Two different non-empty sets
    assert(!is_subset({0}, {1}));

    // Proper subset
    assert(is_subset({1, 2, 3}, {2}));

    // Unordered proper subset
    assert(is_subset({1, 3, 2}, {2}));

    // All values in subset must be in superset
    assert(!is_subset({1, 2, 3}, {2, 2}));
    assert(is_subset({1, 2, 2, 3}, {2, 2}));
}


bool is_subset(std::vector<int> a, std::vector<int> b)
{
    using std::begin;
    using std::end;

    // The includes() algorithm requires sorted inputs
    std::sort(begin(a), end(a));
    std::sort(begin(b), end(b));
    return std::includes(begin(a), end(a),  begin(b), end(b));
}

其他一些观察结果:

  • 熟悉C ++标准库。请注意,使用vector我不需要使用new[]delete[]来管理内存,并且通过使用<algorithm>中的函数,我节省了很多时间重新实现标准转换 - 以及代码也变得更加清晰。
  • 尽可能避免内存管理 - 尽可能选择标准集合,否则选择智能指针对象,只有在无法避免时才使用原始C样式指针。并且总是清理你分配的内存,即使程序即将退出。这不仅可以更容易地使用Valgrind等工具来了解程序的正确性,还可以在更大的程序中重复使用您的功能。