如何同时从数组中删除多个元素

时间:2016-05-01 15:29:04

标签: c arrays

我想使用索引数组从数组中删除多个元素,这是我的代码:

// b is an index array, n is size of b,
// player is the array need to be delete elements,
// size is the size of player
void play_cards(int b[],int n,int player[],int *size){
    int i;
    for(i = 0; i < n; i++)
        delete_cards(b[i],player,size);
}

void delete_cards(int n,int player[],int *size){
    int i;
    for(i = n; i < *size; i++)
        player[i] = player[i+1];   
    *size -= 1;
}

int main(void){

  int player[10] = {1,2,3,3,4,4,5,5,6,7};
  int index[6] = {2,3,4,5,6,7};
  int size = 10;

  play_cards(index,6,player,&size);

  for(int i = 0; i < size; i++)
       printf("%d|",player[i]);
  puts("");

  return 0;
}

我希望打印的玩家应该是1,2,6,7而不是1,2,3,4。我该如何解决?

4 个答案:

答案 0 :(得分:3)

首先,我不会调用函数delete_cards,因为它表示它会删除多张卡片而不会删除它们 - 只需delete_card即可使事情更清晰。

无论如何 - 当您在player数组中播放所有卡之前更改index数组时,您可以更改索引的含义。这就是您当前代码无法正常工作的原因。

所以你可以做两件事:

a)首先播放所有卡,然后删除播放的卡片。这可以通过首先使用-1标记已播放的卡片然后设置一个循环来删除所有元素-1

来完成

b)播放一张卡片,删除它并通过将它们减一来调整index中的剩余元素。注意:此解决方案要求index已排序(最低位)。

解决方案a)看起来像这样:

void delete_played_cards(int player[],int *size)
{
    int i;
    int next_pos = 0;
    int deleted = 0;
    for(i = 0; i < *size; i++)
    {
        if (player[i] != -1)
        {
            player[next_pos] = player[i];
            if (i != next_pos)
            {
                player[i] = -1;
            }
            ++next_pos;
        }
        else
        {
            ++deleted;
        }
    }

    *size -= deleted;
}

void play_cards(int b[],int n,int player[],int *size)
{
    int i;

    for(i = 0; i < n; i++)
    {
        player[b[i]] = -1;  // Mark card as played
    }

    delete_played_cards(player,size);
}

int main(void)
{
  int player[10] = {1,2,3,3,4,4,5,5,6,7};
  int index[6] = {2,3,4,5,6,7};
  int size = 10;

  play_cards(index,6,player,&size);

  for(int i = 0; i < size; i++)
       printf("%d|",player[i]);
  puts("");

  return 0;
}

答案 1 :(得分:2)

修改play_cards

void play_cards(int b[],int n,int player[],int *size)
{
int i;
for(i = n-1; i >= 0; i--)
    delete_cards(b[i],player,size);
}

这将从数组末尾开始删除。 正如BLUEPIXY所述。

答案 2 :(得分:0)

这是一个可以使用的伪代码:

given a sorted list, 1..n

for i = 2 up to length of list:
  if list[i] is equal to list[i-1]:
    shift the sublist [2..] 1 position to the left
  else
     increment i by 1

答案 3 :(得分:-1)

如果您想在不使用循环的情况下轻松有效地删除,可以使用memcpy

#include <stdio.h>
#include <string.h>
#define INDEX_MAX 6

int main ()
{
   int size = 10;
   int src[] = {1,2,3,3,4,4,5,5,6,7};
   int index[] = {2,3,4,5,6,7};
   int x;

   size = size - INDEX_MAX; 
   memcpy(src+2, src+8, sizeof(int)*(size-2));// - 2 since index 1 and 2 remains in the array

   for(x = 0; x < size; x++){
       printf("%d",src[x]);
   }

   return(0);
}