使用指针删除 C 中的重复项时出错



我的代码出错,我试图获取重复项并将其删除。

但是当我尝试这样做时,它不会删除任何内容,并且仍然在输出中为我提供与原始值相同的值。

下面我展示了这两种方法。

void print_array只是打印出数组。

void removeDups 我想要的是获取重复项并删除它们并打印新数组。

让我知道错误发生的位置。

此外,还建议使用指针表示法。谢谢!

void removeDups(int *array, int *length)
{
*length = 10;
int i, j;
for(i = 0; i < *length; i++)
{
for(j = 0; j < *length; j++)
{
if(array[i] == array[j])
{
array[j] = array[*length-2];
length++;
}
}
}
printf("Number of new elements: %d,", *length);
printf(" new elements: ");
for(i = 0; i < *length; i++)
{
printf("%d " , array[i]);
}
}
void print_array(int *array, int length)
{
printf("Number of elements: %d,", length);
int i;
printf(" Orginal elements: ");
for(i = 0; i < length; i++)
{
printf("%d " , array[i]);
}
}
int main()
{
int array [10];
int i, number;
int size = 10;
int *length;
length = &size;
for(i = 0; i < size; i++)
{
number = rand() % 10 + 1;
array[i] = number;
}
print_array(array, size);
printf("n");
removeDups(array, length);
return 0;
}

输出:

元素数量:10,原始元素:4 7 8 6 4 6 7 3 10 2

新元素数量:3,新元素:10 6 8

这部分

if(array[i] == array[j])
{
array[j] == array[i];
length++;
}

没有意义。 这

array[j] == array[i];

表达是一种比较。我想你想影响array[i]array[j]

array[j] = array[i];

但你刚刚确认它们是相同的。
然后你递增length,这在这种情况下是危险的,而且毫无意义。

如果顺序不重要,请将array[j]替换为array[length - 1]然后递减length
如果顺序很重要,则将每个值从array[j + 1]移动到array[length - 1]移动到array[j]array[length - 2],然后递减length

同时删除

length = 10;

线。这里length当你调用removeDups时已经是10,如果你用一个较小的数组调用它,你将在你的数组之外读取。您还只需要将值与其后面的值进行比较;比较array[i]时,已经将其与array[0]array[i - 1]之间的所有值进行了比较。

for(i = 0; i < *length; i++)
{
for(j = i + 1; j < *length; j++)
{
if(array[i] == array[j])
{
array[j] = array[*length - 1];
(*length)--;
}       
}
}

编辑:Riiight,长度是 int*!

订购版本:

for(i = 0; i < *length; i++)
{
for(j = i + 1; j < *length; j++)
{
if(array[i] == array[j])
{
for (int k = j; k < *length - 1; ++k)
{
array[k] = array[k + 1];
}
(*length)--;
j--; //I forgot this, but once you moved all values array[j] will have been updated and you must compare it again.
}       
}
}

或者使用辅助阵列,正如 gsamaras 建议的那样。

请修复代码中的所有警告 - 例如,您可以在 GCC 中启用WallWextra标志。

然后我看到的一个逻辑错误在这里:

array[j] == array[i]

您要分配的位置,而不是比较,因此请将其更改为:

array[j] = array[i]

此外,当您打印删除重复值的数组时,您将迭代直到end,但此变量是未声明的。


我认为您需要退后一步并使用额外的数组进行操作,该数组将是删除重复元素的旧数组。在这种情况下,您可以将代码修改为如下所示的内容:

#include <stdio.h>
#include <stdlib.h>
void removeDups(int *array, int length)
{
int array_no_dups[length];
int unique_n = 0;
for(int i = 0; i < length; ++i)
{
int found = 0; // flag
//check if element already in the array without duplicates
for(int j = 0; j < unique_n; j++)
{
if(array[i] == array_no_dups[j])
found = 1;
}
// If not found
if(!found)
// then append it to the array without duplicates
array_no_dups[unique_n++] = array[i];
}
printf("Number of new elements: %d,", unique_n);
printf(" new elements: ");
for(int i = 0; i < unique_n; i++)
{
printf("%d ", array_no_dups[i]);
}
}
void print_array(int *array, int length)
{
printf("Number of elements: %d,", length);
printf(" Orginal elements: ");
for(int i = 0; i < length; i++)
{
printf("%d " , array[i]);
}
}
int main()
{
int array[10];
int size = 10;
for(int i = 0; i < size; i++)
array[i] = rand() % 10 + 1;
print_array(array, size);
printf("n");
removeDups(array, size);
return 0;
}

输出:

Number of elements: 10, Orginal elements: 4 7 8 6 4 6 7 3 10 2 
Number of new elements: 7, new elements: 4 7 8 6 3 10 2 

现在,如果您真的想就地删除重复项,那么每次找到重复值时,都需要将其第二次出现与数组的最后一个元素交换(这将由您将维护的计数器索引(。当然,您现在需要小心您的索引。

例如,您可以像这样就地调用它(像这样调用方法:removeDups(array, &size);(:

void removeDups(int *array, int *length)
{
int original_len = *length;
for(int i = 0; i < original_len - 1; ++i)
{
for(int j = i + 1; j < *length; ++j)
{
if(array[i] == array[j])
{
array[j] = array[*length - 1];
(*length)--;
j--;  // since the new `array[j]` element might be also a duplicate of `array[i]`
}
}
}
printf("Number of new elements: %d,", *length);
printf(" new elements: ");
for(int i = 0; i < *length; i++)
{
printf("%d ", array[i]);
}
}

现在输出将是:

新元素数量:7

,新元素:4 7 8 6 2 3 10

不保留元素的原始顺序。

如果要就地执行此操作并保留原始顺序,则不应每次找到重复项时都交换,而应将所有子数组从 (j+1(-th 元素向左移动一个位置。

就时间复杂度而言,这是一个成本更高的操作,但这是权衡,你更慢,但你保持秩序。你应该做你的应用程序要求你做的事情,即如果顺序很重要,则使用移位方法,如果顺序无关紧要,则使用交换方法。

最新更新