我的代码出错,我试图获取重复项并将其删除。
但是当我尝试这样做时,它不会删除任何内容,并且仍然在输出中为我提供与原始值相同的值。
下面我展示了这两种方法。
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 中启用Wall
和Wextra
标志。
然后我看到的一个逻辑错误在这里:
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 元素向左移动一个位置。
就时间复杂度而言,这是一个成本更高的操作,但这是权衡,你更慢,但你保持秩序。你应该做你的应用程序要求你做的事情,即如果顺序很重要,则使用移位方法,如果顺序无关紧要,则使用交换方法。