【问题标题】:Finding the Intersect of 'n' Generic Arrays查找“n”个泛型数组的交集
【发布时间】:2013-10-31 17:27:41
【问题描述】:

编辑:添加了更多细节。

我正在尝试编写一个算法来找到 n 个数组的交集(所有点的共同点)。我的程序采用这些数组并将它们存储在一个二维数组中,在该数组上进行操作。例如,这里是一个示例 main 方法:

int a[] = { 12, 54, 42 };
int b[] = { 54, 3, 42, 7 };
int c[] = { 3, 42, 54, 57, 3 };

IntersectionTableau<int> x(3);    // Where 3 is the max number of arrays allowed
                                  // to be stored.
x.addArray(a, 3);
x.addArray(b, 4);
x.addArray(c, 9);
x.run();            // Finds the intersection.

这些添加的数组将存储在T** arrays 中,它们的大小将存储在int* sizes 中。 T 是泛型类型。什么是一种有效的算法,可以让我在可变数量的泛型类型数组上执行此操作?

这是我目前正在尝试做的事情:

template <class T>
inline
void IntersectionTableau<T>::run() {
    T* commonElements = d_arrays[0];
    for (int i = 1; i < d_currentNumberOfArrays; ++i) {
        commonElements = getIntersection(commonElements, d_arrays[i], d_sizes[i - 1], d_sizes[i]);
    }
    d_results = commonElements;
}



template <class T>
inline
T* IntersectionTableau<T>::getIntersection(T* first, T* second, int sizeOfFirst, int sizeOfSecond) {
    T* commonElements;
    if (sizeOfFirst > sizeOfSecond) {
        commonElements = new T[sizeOfFirst];
    } else {
        commonElements = new T[sizeOfSecond];
    }
    for (int i = 0; i < sizeOfFirst; ++i) {
        for (int j = 0; j < sizeOfSecond; ++j) {
            if (first[i] == second[i]) {
                commonElements[i] = first[i];
            }
        }
    }
return commonElements;

}

第一个函数获取前两个数组并将它们发送给第二个函数,第二个函数返回这两个数组之间的交集数组。然后,第一个函数将交集数组与d_arrays 中的下一个数组进行比较,依此类推。我的问题是当我从d_results 打印出一个元素时,会产生一个垃圾值,我不确定为什么。有人可以告诉我我做错了什么,或者是更好的方法来完成这个吗?

【问题讨论】:

    标签: c++ arrays algorithm generics intersection


    【解决方案1】:

    代码中至少有两个问题:


    if (first[i] == second[i])
    

    这应该是if (first[i] == second[j])


    commonElements[i] = first[i];
    

    这更难解决。我想你想要另一个变量(ij 都不是);我们就叫它k

    commonElements[k++] = first[i];
    

    无论如何,既然您可以使用 C++,您可以使用 std::vector 代替。它在里面存储它的大小;这将减少混乱:

    template <class T>
    std::vector<T> // note: adjusted the return type!
    IntersectionTableau<T>::getIntersection(...)
    {
        std::vector<T> commonElements;
        for (int i = 0; i < sizeOfFirst; ++i) {
            for (int j = 0; j < sizeOfSecond; ++j) {
                if (first[i] == second[j]) {
                    commonElements.push_back(first[i]);
                }
            }
        }
        return commonElements;
    }
    

    您也可以将firstsecond 转换为向量(尽管您现在不会从中受益太多)。

    这里有几点需要注意:

    • 我将返回类型改为vector&lt;T&gt;
    • 旧版本,返回一个数组,需要额外的代码来指定其结果的长度;此版本返回 vector&lt;T&gt; 对象内的长度
    • 返回数组的旧版本需要在稍后的某个位置使用delete[] array,以防止内存泄漏
    • vector-to-pointer hack &amp;commonElements[0] 不适用于空的vector

    如果您的其他代码使用数组/指针,您可以使用vector-to-pointer hack &amp;commonElements[0],但在函数之外,以遵守生命周期规则:

    T* commonElements = NULL;
    for (int whatever = 0; whatever < 10; ++whatever)
    {
        std::vector<T> elements = xxx.getIntersection(...); // will work
        commonElements = &elements[0]; // can pass this pointer to a function receiving T*
        print(commonElements); // will work
    }
    print(commonElements); // cannot possibly work, will probably segfault
    print(elements); // cannot possibly work, and compiler will reject this
    

    【讨论】:

    • (first[i] == second[i]),真不敢相信我错过了!除此之外,如果我要使用向量,我是否可以将其转换为 T* 类型以返回它?我不熟悉std::vector。虽然反应很好,但帮助很大。谢谢。
    • 好的,所以我正在使用您的 std::vector 方法,该方法似乎可以正常工作(程序正确构建),但是,当使用语句 return &amp;commonElements[0] 返回时,程序会产生段错误。当我使用我的代码时,这不会发生,除了更正if (first[i] == second[j])。你知道为什么会发生这种情况吗?
    • 它是segfaults,因为你正在返回一个本地对象的地址,从函数返回后将被删除。
    • 有没有其他方法可以做到这一点(将向量作为数组返回)而不被删除?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多