C-从数组中删除重复项并将这些重复项存储在另一个数组中

时间:2018-12-03 00:52:41

标签: c arrays sorting integer

我有一个名为allnumbersarray的数组,我需要删除该数组的重复项并将它们存储在另一个名为uniqueprimes的数组中。 allnumbersarray由质数组成。当我尝试使用if-else if语句时,输出变得混乱,许多元素变为0,并且不再排序。这是我尝试过的方法,不确定要更改什么:

int temp[], temp2[];
int removeDuplicates()
    {
        int n, j =0;
        temp[n];
        temp2[n];

        // Start traversing elements

        for (int i=0; i<n-1; i++){

            // If current element is not equal
            // to next element then store that
            // current element
            if (allnumbersarray[i] != allnumbersarray[i+1]){
                temp[j++] = allnumbersarray[i];
            }
            else if(allnumbersarray[i] == allnumbersarray[i+1])
                temp2[j++] = allnumbersarray[i];

        }
        // Store the last element as whether
        // it is unique or repeated, it hasn't
        // stored previously
        temp[j++] = allnumbersarray[n-1];

        // Modify original array
        for (int i=0; i<j; i++){
            allnumbersarray[i] = temp[i];
        }

        printf("\n\nprimes array with duplicates removed:\n");
          for (int i = 0; i < j; i++)
              printf("%d\n", allnumbersarray[i]);


        return j;
    }

1 个答案:

答案 0 :(得分:1)

您尚未创建MCVE(Minimal, Complete, Verifiable Example,这是一个问题。如果提供的代码是MCVE,则以下某些批评可能无关紧要。

代码片段(temptemp2)中的全局变量太多,也不够(您尚未显示allnumbersarray[]的定义方式)。使用参数传递函数。

您说您有:

int temp[], temp2[];
int removeDuplicates()
    {
        int n, j =0;
        temp[n];
        temp2[n];
        for (int i=0; i<n-1; i++){

您不会显示temptemp2在哪里定义了大小,这行之前应该有extern。 (我不确定您为什么不使用temp1temp2,但这是常见的特质。)

该函数未使用原型定义;使用int removeDuplicates(void)表示应在不带参数的情况下调用它。就目前而言,同一文件中的代码可能会写removeDuplicates(3.14, "astronomy");,并且编译器没有义务发现差异,因为函数定义没有给出该函数的原型。

函数内部有一个未初始化的变量n;它的价值是不确定的。由于某些无法解释的原因,您有temp[n];temp2[n];这两个语句从可疑声明的数组中的不确定位置(或更可能在外部)读取。如果幸运的话,编译器可能会删除这些引用,因为它们不会影响计算。但是它们被误导了两次-一次是因为它们什么都不做,一次是因为他们使用未初始化的变量来索引数组。

然后,您可以将此未初始化的变量n用作主for循环的绑定。这不会幸福地结束。您永远不会使用精心存储在temp2中的值。

我认为您需要彻底重新设计功能。例如,您可以使用:

 int removeDuplicates(int *n_values, int *values, int *dups)
 {

其中*n_values是源数组(values)中的条目数,它成为输出数组之一。它已通过引用传递,因此您可以向调用函数识别在完成重复删除之后values数组中有多少个唯一条目(在开始处使用int n = *n_values;,在*n_values = …new size…;结束)。 dups数组等效于您的temp2。它被假定为“足够大”(实际上是一个危险的假设)。该函数将直接返回dups中的条目数,就像当前函数是否正确编写一样。

在当前方案中的某些地方,您必须将源数组(values)中的唯一值复制到备用空间中,只需简单地将其复制回来即可。一种更好的算法使用两个索引逐步遍历源数组,即当前读取位置和当前写入位置。当发现相邻的重复项时,可以增加读取位置而不增加写入位置。这意味着您最终根本不需要temp数组。

您还使用相同的代码“删除重复项”,但是该算法仅查找相邻的重复项。如果您有一个输入列表(int[]){ 2, 3, 3, 5, 7, 7, 3, 11, 11, 13, 17, 19, 11 }(即compound literal),则您的代码将不会发现第三个3或第三个11。目前尚不清楚这是否是一个问题-可能是重复项只能彼此相邻发生,在这种情况下,如果重复项不必相邻,则不必像在分析中那样复杂。

这至少可以给您一些思考。

下次,请确保发布更完整的MCVE;您提交的内容太小,无法提供舒适感。并避免像鼠疫这样的全局变量。大多数功能应具有参数,以标识它们将要进行的工作。