在C语言中删除数组元素

5
我编写了以下程序,用于删除用户输入的数组元素。
#include <stdio.h>
#include <conio.h>

void main() {
    int j, i, a[100], n, key, l;
    clrscr();
    printf("Enter the number of elements:");
    scanf("%d", &n);
    printf("\nEnter the elements:\n");
    for (i = 0; i < n; i++)
        scanf("%d", &a[i]);
    printf("\nEnter the element to delete:");
    scanf("%d", &key);
    l = n;  //Length of the array
    for (i = 0; i < l; i++) {
        if (a[i] == key) {
           for (j = i; j < l; j++)
               a[j] = a[j + 1];
           l--;    //Decreasing the length of the array
        }
    }

    printf("\nThe new array is \n");
    for (i = 0; i < l; i++)
        printf("%d ", a[i]);
     getch();
}

大部分输入都能正常工作,但当输入类似于:1 2 2 3 5(这里2连续重复)并且要删除的元素是2时,输出结果为1 2 3 5

我该如何修改程序以删除所有输入元素的实例?


3
这是作业还是编码测试? - Michael Dautermann
7个回答

5
在下面的示例中,将l--替换为i--。
if(a[i]==key)
  {
   for(j=i;j<l;j++)
    a[j]=a[j+1];
   l--;    //Decreasing the length of the array
   i--;    //check again from same index i
  }

2
抱歉翻出老问题,但是当j指向数组的最后一个元素时,a[j]= a[j+1]会失败吗? - bobby

3

如果您不关心数组中元素的顺序,您可以将数组的最后一个元素移动到新形成的空隙中(巧妙地将数组的长度减少一)。这比将元素向下移动要高效得多:在计算机科学术语中,这使删除一个元素的时间复杂度为O(1),而不是O(N)。

a[i] = a[--l];

如果您的 i 索引正在循环数组,则需要再次循环此元素:
a[i--] = a[--l];

例如,要从长度为'l'的数组中删除所有元素'3':
for (i = 0; i < l; ++i) {
    if (a[i] == 3) {
        a[i--] = a[--l];
    }
}

如果您关心数组元素的顺序,使用memmove比手动移动元素更有效率。它被设计用于在源内存和目标内存重叠的情况下使用。
memmove(a + i, a + i + 1, sizeof(a[0]) * (l - i - 1));

2

其他人已经给出了2种解决方案......我认为了解为什么会发生这种情况也很好:)

让我们以您的例子1、2、2、3、5为例,一行一行地跟随代码

i = 0;             /* first time through the loop; i "points" to 1 */
if (a[i] == 2) ... /* nope; next loop */
i = 1;
if (a[1] == 2) ... /* yes! let's go inside the if */
                   /* move all elements back
                   ** and "decrease" array length */
                   /* array is now 1, 2, 3, 5 */
                   /* next loop */
i = 2;
if (a[i] == 2) ... /* nope; OH! Wait ...
                   ** a[1] is the new 2 and it wasn't checked */

+1:在看到你的帖子之前,我非常困惑。关键是要减少循环计数器。谢谢! - 0x2b3bfa0

1

将 "if" 改为 "while":

    for(i=0;i<l;i++)
    {
        while (i<l && a[i]==key)
        {
            for(j=i;j<l;j++)
                a[j]=a[j+1];
            l--;    //减少数组的长度
        }
    }


我担心我的技巧有缺陷 - 删除最后一个元素可能会无限循环(取决于a[l]的值,它超出了数组范围)。添加i<l来修复它。 - ugoren

0
#include<stdio.h>


int main(){
int size;
int array[20];
int delete_pos;
int i;

printf("Enter the Size of the Array :");
scanf("%d",&size);


for(i=0;i<=size-1;i++){                                //no of elements taken are 1 less than size of the array asked.
    printf("\nEnter the element[%d] :",i+1);
    scanf("%d",&array[i]);
}

printf("\nEnter the Position of the array to be deleted :");
scanf("%d",&delete_pos);


for(i=delete_pos-1;i<=size;i++){                    //every element of the array is replaced by array on next position.
    array[i]=array[i+1];}

size=size-1;                                       // Reducing the size of the array as one element is deleted.
printf("Your new array is \n");
for(i=0;i<=size-1;i++){                            //printing the entire new array.
    printf("%d ",array[i]);

}
printf("\n\n");
return 0;
}

请在您的回答中添加一些描述。@Dhruv Aditya Mittal - Rohit Poudel
首先,它会询问数组的大小,然后询问要写入数组的元素。在获取元素后,它会询问要从数组中删除哪个数组。最终输出将打印数组中剩余的元素,即新数组。@RohitPoudel - Dhruv Aditya Mittal

0

使用一个新的数组。

int array[l];
int k=0;
for(i=0;i<l;i++)
{
 if(a[i]!=key)
 {
  array[k]=a[i];
  k++;
 }

}

只要注意数组的大小就可以了。我没有检查它。 - FrankTan

0

你使用的两层嵌套 for 循环方法过于复杂。你可以使用一个索引 i 扫描数组,并将所有与 key 不同的元素复制到另一个索引 len 中。最终的数组长度即为 len 的最终值。

这是修改后的版本:

#include <stdio.h>
#include <conio.h>

int main(void) {
    int a[100];
    int i, n, key, len;

    clrscr();
    printf("Enter the number of elements: ");
    if (scanf("%d", &n) != 1) {
        printf("invalid input\n");
        return 1;
    }
    if (n < 0 || n > 100) {
        printf("invalid number of elements\n");
        return 1;
    }
    printf("\nEnter the elements:\n");
    for (i = 0; i < n; i++) {
        if (scanf("%d", &a[i]) != 1) {
            printf("invalid input\n");
            return 1;
        }
    }
    printf("\nEnter the element to delete: ");
    if (scanf("%d", &key) != 1) {
        printf("invalid input\n");
        return 1;
    }

    for (i = len = 0; i < n; i++) {
        if (a[i] != key)
           a[len++] = a[i];
    }

    printf("\nThe new array is:\n");
    for (i = 0; i < len; i++)
        printf("%d ", a[i]);
    printf("\n");
    getch();
    return 0;
}

注意事项:

  • main函数的原型不带参数为int main(void),成功时返回0被认为是良好的编程风格。

  • 始终测试scanf()的返回值。这可以防止许多错误和无效输入的未定义行为。当输入无效时,它还可以节省很多时间,避免在错误的地方查找。

  • 避免将变量命名为l,因为在许多等宽字体中,它看起来太接近1

  • 始终以换行符结束程序输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接