2个动态分配数组c++的交集

Intersection of 2 dynamically allocated arrays c++

本文关键字:c++ 动态分配 数组 2个      更新时间:2023-10-16

我正在尝试创建一个函数,该函数将查找比较数组1和数组2的两个动态分配数组的交集。对于数组1中不在数组2中的任何值,应该在数组1中删除这些值,以便数组1现在只保存两个数组的公共值(没有重复)。我不能在类中使用向量、哈希或任何其他当前函数之外的东西:

这是我到目前为止的代码:

bool IntSet::contains(int val) const
{
   for (int i = 0; i < numValues; i++)
{
    if (set[i] == val)
        return true;
}
return false;
}

此函数将整数参数与当前存储在数组中的值进行比较。。。如果数组中有一个值,则返回true,否则返回false;

下一个函数接收一个值并从数组中删除该值:

void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
    if (set[i] == val)
        for (int j = 0; j < numValues; j++)
            set[j] = set[j + 1];
}
numValues--;
}

这就是我遇到的问题,下一个函数应该遍历一个数组,并将这些值与另一个数组中的值进行比较。。。如果一个数组中的一个值在另一个数组,它应该跳过它,但如果一个值不在调用函数的数组中,它应该从调用数组中删除该值:

void IntSet::removeDifferent(const IntSet &set2)
{
  for (int i = 0; i < set2.size(); i++)
  {
    if (!set2.contains(set[i]))
    {
        remove(set[i]);
    }
  }
}

我在removeDifferent()函数上尝试了大约50种不同的变体,但我似乎无法理解这一点。有人能给我指正确的方向吗?

您正在通过set2的索引迭代i,但随后您正在测试set[i]。试试这个:

void IntSet::removeDifferent(const IntSet &set2)
{
    for (int i = 0; i < numValues; ) {
        if (!set2.contains(set[i])) {
            remove(set[i]);
        } else {
            i++;
    }
}

注意,我还从for循环头中删除了i++。这是因为当移除一个元素时,下面的所有元素都会下移,所以下一个元素会在数组中占据它的位置。如果递增i,它将跳过该元素。

您还需要修复remove。它应该从i开始它的内部循环,所以它只在移除元素后向下移动元素,并且它应该在numValues-1停止,所以它在复制set[j+1]时不会尝试访问数组外部。作为一种优化,一旦找到匹配项,它就可以将break从外循环中移除(我假设IntSet不允许重复,因为您只将numValues递减1)。

void IntSet::remove(int val)
{
    for (int i = 0; i < numValues; i++)
    {
        if (set[i] == val) {
            for (int j = i; j < numValues - 1; j++) {
                set[j] = set[j + 1];
            }
            break;
        }
    }
    numValues--;
}

问题出在remove()函数中:

void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
    if (set[i] == val)
        for (int j = 0; j < numValues; j++)
            set[j] = set[j + 1];
}
numValues--;
}

你可以在这里用纸和铅笔自己弄清楚为什么这是错误的。从一个典型的例子开始:假设您在五元素数组的第三个元素中找到了要查找的值:

if (set[i] == val)

在这个例子中,i将被设置为2,而numValues将被设置成5。val是什么并不重要。不管它是什么,当i是2,numValues是5时,你就会发现它:你在五元素数组的第三个元素中发现了它。记住这一点。

现在,您知道您现在应该移除这个五元素数组中的第三个元素。但你认为接下来会发生什么:

        for (int j = 0; j < numValues; j++)
            set[j] = set[j + 1];

好吧,使用前面提到的纸和铅笔,如果你计算出来,就会发生以下情况:

  • 集合[1]将被复制到集合[0]
  • 集合[2]将被复制到集合[1]
  • 集合[3]将被复制到集合[2]
  • 集合[4]将被复制到集合[3]
  • 集合[5]将被复制到集合[4]

这里有两个问题:

A) 没有set[5]。回想一下,这是一个五元素数组,因为您只有set[0]set[4]

B) 您不应该将数组中的所有内容都复制到一个元素中。您必须仅复制要删除的元素之后的元素

解决这两个问题,你可能会发现一切都会正常工作。