【问题标题】:How to find the difference between two arrays in C?如何在C中找到两个数组之间的差异?
【发布时间】:2018-03-07 14:52:57
【问题描述】:

我一直在尝试编写 c 程序来查找两个数组之间的并集、交集和差异,虽然前两个结果很好,但我在找到两个数组之间的差异时遇到了一些麻烦。不同的是,我的意思是array1中的每个元素,而不是array2中的每个元素。

我希望第三个数组包含 array1 中不在 array2 中的每个元素,反之亦然。所以如果array1是[1,2,3],arr2是[3,4,5],那么arr3是[1,2]。如果两个数组的大小不同,我也不确定如何找到差异。

我的输出是一堆零和负数:

区别是:1

区别是:2

区别是:-14200

区别是:0

区别是:-14340

区别是:0

这是我一直在使用的代码:

#include <stdio.h>

int main()
{
  int arr1[100];
  int arr2[100];
  int size1, size2, i, j, s=0;

  //enter array size
  printf("\nPlease enter array1 size: \n");
  scanf("%d", &size1);
  printf("\nPlease enter array2 size: \n");
  printf("\n--------------------------- \n");
  scanf("%d", &size2);

  //setting up a third array to contain the difference
  int tot_size = size1+size2;
  int arr3[tot_size];


  //enter array elements
  for(i=0;i<size1;++i)
  {
    printf("\nPlease enter array1 element %d:\n", i);
    scanf("%d", &arr1[i]);
  }
  printf("\n--------------------------- \n");
  for(i=0;i<size2;++i)
  {
    printf("\nPlease enter array2 element %d:\n", i);
    scanf("%d", &arr2[i]);
  }

  printf("\n--------------------------- \n");


  //compare the two arrays, if two elements are not equal
  //store them in a third array
  for(i = 0; i < size1; i++)
  {
    for(j = 0; j < size2; j++)
    {
      if(arr1[i] != arr2[j])
      {
        arr3[s] = arr1[i];
        ++i;
        ++j;
        ++s;
      }
    }
  }

  for(i=0;i<s;++i)
    printf("\nThe difference is: %d\n", arr3[i]);

}

任何帮助都将不胜感激,因为我是 C 新手,还有很多东西要学。

【问题讨论】:

  • 定义“差异”。如果一个数组大于另一个数组会怎样?为什么要将整行与循环中的一个元素进行比较?
  • 你的最后一个不应该去“tot_size”,而应该去“s”。另外,如果我理解正确,for 中的 if 条件是可疑的,因为它会为与 arr2[j] 不同的每个 arr1[i] 添加一个新的“差异”。如果 arr1 大小为 10,arr2 大小为 20,那么您将有 200 个可能性!
  • 您是否也不想存储 arr2 值?
  • 您好,感谢您的回复。不同之处在于:数组 1 中的每个元素,而不是数组 2 中的每个元素。所以我想要第三个数组中的元素。
  • 我已编辑问题文本以包含差异定义,并说明两个不同大小数组的问题。

标签: c arrays array-difference


【解决方案1】:

如果两个数组之间的差异是第一个而不是第二个和第二个不是第一个的数字,您可以简单地执行以下操作:

  • 创建一个结果数组,并将第一个和第二个数组复制进去。

    arr1 = [3, 5, 7, 0]

    arr2 = [1, 10, 5]

    arr3 = [arr1, arr2] ==> [3, 5, 7, 0, 1, 10, 5]

  • 然后,对数组进行排序(使用 qsort 或任何其他排序函数)

    arr3 = [0, 1, 3, 5, 5, 7, 10]

  • 最后,删除多次出现的数字(排序步骤只需一次就可以轻松完成)

    arr3 = [0, 1, 3, 7, 10]


评论后:那么,arr1 和 arr2 之间的区别是 arr1 中的数字而不是 arr2 中的数字吗?您的第一个代码更有意义。

为了方便你,你应该做一些函数。

  • 制作一个“IsNumberInArray”函数

    bool IsNumberInArray(int number, int *array, size_t arraySize)

我把实现留给你(如果数组是排序的,你可以实现二分搜索,否则你可以做一个好的旧循环)。

  • 然后,对于 arr1 中的每个数字,如果 IsNumberInArray(arr1[i], arr2, size2) 为 false,则在 arr3 中添加 arr1[i]。

基本上,这几乎就是您所做的。您的问题在于“反转”条件(数字是否在第二个数组中?)以及“如何轻松地从第二个循环中中断”。该功能将提供。

请注意,由于 arr3 将只保留 arr1 中不在 arr2 中的数字,因此 arr3 的大小可以为最大 size1。这就是为什么我首先假设您想要 arr1 和 arr2 中的 uniq 编号,因为 tot_size 是 size1 + size2。


通常,我不会为“简单”的问题提供代码,因为如果你不能自己解决,那就意味着你需要练习,给你答案对你没有用,但是自从 sg7 做到了,拿着没意义(而且你暂时不能使用房间),所以这里是算法的实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

bool IsNumberInArray(int number, int *array, size_t arraySize)
{
    for (size_t i = 0; i < arraySize; ++i) {
       if (array[i] == number) {
           return (true);
       }
    }

    return (false);
}

void DumpArrayContent(int *array, size_t arraySize, char *arrayName)
{
    printf("%s has %zu elements:\n", arrayName ? arrayName : "array", arraySize);               
    for (size_t i = 0; i < arraySize; ++i) {
        printf("%d ",array[i]);
    }
    printf("\n");    
}

int main(void)
{
    int arr1[] = {1,2,3,4,7,8,9};
    int arr2[] = {3,4,5};

    size_t s1 = sizeof(arr1)/sizeof(*arr1);
    size_t s2 = sizeof(arr2)/sizeof(*arr2);

    int    arr3[s1];
    int    s3 = 0;

    for (size_t i = 0; i < s1; ++i) {
        if (!IsNumberInArray(arr1[i], arr2, s2)) {
           arr3[s3] = arr1[i];
           s3++;
        }
    }

    DumpArrayContent(arr1, s1, "arr1");
    DumpArrayContent(arr2, s2, "arr2");
    DumpArrayContent(arr3, s3, "arr3");

    return 0;
} 

我认为没有更“有效”的实现方式,因为经过编译器优化后,生成的可执行文件将完全相同。如果没有激活编译器优化,sg7 代码会更“有效”,因为它是直截了当的(我的有函数调用)。看你喜欢哪一个。

【讨论】:

  • 哇!多么聪明的解决方案!非常感谢,我会努力实现的。
  • 谢谢!祝您实施顺利。请记住,这主要是一个幼稚的解决方案,并且可以通过某种方式进行改进,但我认为这是一个很好的第一步。
  • 嗯,我刚刚记得,我希望第三个数组包含 array1 中不在 array2 中的每个元素,反之亦然。所以如果array1是[1,2,3],arr2是[3,4,5],那么arr3是[1,2]。你对如何做到这一点有什么建议吗?
  • 抱歉汤姆回答晚了,再次感谢您的帮助。我正在尝试实现您建议的功能,但是如何将整数与整个数组进行比较?在我的脑海中,我也必须遍历 array2,因为我无法将整数与指针(数组)进行比较。
  • "IsNumberInArray" 函数的目的是告诉你一个数字是否在数组中(返回 true)或不在数组中(返回 false)。如果 arr1 = [1, 2, 3] 和 arr2 = [3, 4, 5],则 "IsNumberInArray(arr1[0], arr2, size2)" 应返回 false,因为 arr1[0](即 1)不是在 arr2 中(即 [3, 4, 5])。相反,"IsNumberInArray(arr1[2], arr2, size2)" 应该返回 true,sinc arr1[2](即 3)确实在 arr2(即 [3, 4, 5])中。你明白吗 ?这是一个非常简单的函数(如果你知道数组是通过二分搜索排序的,你可以改进它)。
【解决方案2】:

我希望第三个数组包含 array1 中不是 在array2中,反之亦然。所以如果array1是[1,2,3],而arr2是 [3, 4, 5],则 arr3 为 [1, 2]。

假设 array1 已经被处理为不包含重复项,
看起来你需要这个:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(void)
{
    size_t i,j,k;
    int s3;

    int arr1[] = {1,2,3,4,7,8,9};
    int arr2[] = {3,4,5};

    size_t s1 = sizeof(arr1)/sizeof(int);
    size_t s2 = sizeof(arr2)/sizeof(int);

    int arr3[s1];
    int e;
    int found = 0;
    k = 0;

    for(i=0; i<s1; i++)
    {
        e = arr1[i]; 
        found = 0;

        for(j=0; j<s2; j++){

           if(e == arr2[j])
           {
               found = 1;
               break;
           }
        }

        if(found == 0){
           arr3[k] = e;
           k++;
        }
    }


    printf("arr1 has %d elements:\n",s1);
    for(i=0;i<s1; i++)
    {
        printf("%d ",arr1[i]);
    }

    printf("\narr2 has %d elements:\n",s2);
    for(i=0;i<s2; i++)
    {
        printf("%d ",arr2[i]);
    }

    printf("\narr3 has %d elements:\n",k);               
    for(i=0;i<k; i++)
    {
        printf("%d ",arr3[i]);
    }

    return 0;
}

输出:

arr1 has 7 elements:                                                                                                                         
1 2 3 4 7 8 9                                                                                                                               
arr2 has 3 elements:                                                                                                                        
3 4 5                                                                                                                                       
arr3 has 5 elements:                                                                                                                        
1 2 7 8 9 

【讨论】:

  • 完美,非常感谢。所以当“for循环”中断时,它返回到“j”循环的开始,并增加j?以便将 arr1 的第 i 个元素与 arr2 的下一个元素进行比较?
  • @DoeJ 当循环中断时,表示来自arr1 的元素存在于arr2 中,无需将其添加到arr3。然后,下一个元素取自arr1,并与arr2 中的所有元素进行比较。当找到元素时,循环中断,如果没有,则将元素添加到arr3
  • @DoeJ。为了澄清,当“for循环”中断时,程序返回以从i循环中获取下一个元素。来自arr1 的下一个元素e 将与arr2 中的所有元素进行比较(除非找到重复项并且循环中断)。循环j 总是从第一个元素重新开始。循环i 总是前进。
  • 太棒了,我明白了。谢谢!
【解决方案3】:

查看您的循环,注意内部 for 循环 j 在 i 的每次迭代中都被初始化为 0。

  for(i = 0; i < size1; i++)
  {
    for(j = 0; j < size2; j++)
    {
      if(arr1[i] != arr2[j])
      {
        arr3[s] = arr1[i];
        ++i;
        ++j;  // so what does this do?
        ++s;
      }
    }
  }
  
  

让我们尝试看看两个具有不同值的数组会发生什么:

arr1 : {1,2}
arr2 : {3,4}


           i   j   s
iteration  0   0   0  => arr3[0] = 1; 
           1   1   1
               2                        j==2 since j++, leaving inner loop j==size2
iteration  2   0   1                    i==2 since i++, leaving outer loop i==size1

最好的办法是在纸上写下你的步骤并检查你的算法,从一个 简单的例子,然后为它创建一个原型例程,如果可行的话继续更大 数组,不同长度的数组,相同的数组等等。

【讨论】:

    猜你喜欢
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 2016-07-21
    • 2013-01-02
    相关资源
    最近更新 更多