c - 使用指针删除 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
解决方案
请修复代码中的所有警告 - 例如,您可以在 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) 个元素向左移动一个位置,而不是每次找到重复项时都进行交换。
就时间复杂度而言,这是一个更昂贵的操作,但这是一种权衡,你速度较慢,但你保持秩序。你应该做你的应用程序要求你做的事情,即如果顺序很重要,请使用移位方法,如果顺序无关紧要,请使用交换方法。
推荐阅读
- css - CSS重复渐变与偏移
- node.js - Mongo 数据库连接
- laravel - Laradock - 本地主机无法在使用 Nginx 的 Windows 7 上运行
- c# - 在 ApplicationDbContext 中的 OnModelCreating 中的 ApplicationUser 上的 Queryfilter 创建 StackOverflowException
- cuda - 如何应对 CUDA 的“cudaMallocPitch”功能中的“cudaErrorMissingConfiguration”?
- java - FXML(JavaFX)中的图像标签,如何使用css设置大小?
- mysql - 如何将 MySQL 用于 .NET Core Azure 函数
- r - 如何检索 GEE 模型拟合中使用的数据框?
- r - 使用坚持()可靠地获取在线文件的最佳方法?
- amazon-web-services - 为基于速率的规则创建 CfnWebACL 失败(AWS CDK WAF 区域)