web-dev-qa-db-fra.com

Supprimer un élément de tableau et décaler les éléments restants

Comment puis-je supprimer un élément d'un tableau et décaler les éléments restants vers le bas. Donc, si j'ai un tableau, 

array[]={1,2,3,4,5} 

et veux supprimer 3 et décaler le reste donc j'ai,

array[]={1,2,4,5}

Comment pourrais-je y parvenir dans le moins de code possible?

18
user103572

Vous devez simplement écraser ce que vous supprimez avec la valeur suivante dans le tableau, propager cette modification, puis garder à l'esprit l'emplacement de la nouvelle fin:

int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
    array[i] = array[i + 1]; // copy next element left

Maintenant, votre tableau est {1, 2, 4, 5, 6, 7, 8, 9, 9}. Vous ne pouvez pas supprimer le 9 supplémentaire puisqu'il s'agit d'un tableau de taille statique, il vous suffit de l'ignorer. Cela peut être fait avec std::copy:

std::copy(array + 3, // copy everything starting here
          array + 9, // and ending here, not including it,
          array + 2) // to this destination

En C++ 11, use peut utiliser std::move (la surcharge de l'algorithme, pas la surcharge de l'utilitaire) à la place.

Plus généralement, utilisez std::remove pour supprimer les éléments correspondant à une valeur:

// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);

Encore plus généralement, il existe std::remove_if.

Notez que l'utilisation de std::vector<int> peut être plus appropriée ici, car c'est un "vrai" tableau de redimensionnement alloué dynamiquement. (En ce sens que demander sa size() reflète des éléments supprimés.)

28
GManNickG

Vous pouvez utiliser memmove() , mais vous devez suivre vous-même la taille du tableau:

size_t array_size = 5;
int array[5] = {1, 2, 3, 4, 5};

// delete element at index 2
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int));
array_size--;

En C++, cependant, il serait préférable d'utiliser un std::vector:

std::vector<int> array;
// initialize array...

// delete element at index 2
array.erase(array.begin() + 2);
21
Adam Rosenfield

std :: copy fait le travail en ce qui concerne le déplacement d'éléments:

 #include <algorithm>

 std::copy(array+3, array+5, array+2);

Notez que la condition préalable à la copie est que la destination ne doit pas être dans la plage source. Il est permis que les plages se chevauchent.

De plus, en raison de la manière dont les tableaux fonctionnent en C++, cela ne "raccourcit" pas le tableau. Cela ne fait que déplacer des éléments en son sein. Il n'y a aucun moyen de changer la taille d'un tableau, mais si vous utilisez un entier distinct pour suivre sa "taille", c'est-à-dire la taille de la partie qui vous intéresse, vous pouvez bien sûr le décrémenter.

Ainsi, le tableau avec lequel vous vous retrouverez sera comme s'il avait été initialisé avec:

int array[] = {1,2,4,5,5};
10
Steve Jessop

Vous ne pouvez pas réaliser ce que vous voulez avec des tableaux. Utilisez des vecteurs à la place et lisez à propos de l'algorithme std :: remove. Quelque chose comme:

std::remove(array, array+5, 3)

fonctionnera sur votre tableau, mais ne le raccourcira pas (pourquoi - parce que c'est impossible). Avec des vecteurs, ce serait quelque chose comme

v.erase(std::remove(v.begin(), v.end(), 3), v.end())
5
zvrba

Selon vos besoins, vous pouvez utiliser des listes stl pour ces types d'opérations. Vous pouvez parcourir votre liste jusqu'à ce que vous trouviez l'élément et l'effacer. Si vous ne pouvez pas utiliser de listes, vous devrez alors tout modifier vous-même, soit à l'aide d'une sorte d'algorithme stl, soit manuellement.

3
PiNoYBoY82

Il est à noter que si l’obligation de préserver l’ordre des éléments est assouplie, il est beaucoup plus efficace de remplacer l’élément supprimé par le dernier élément. 

0
Yuri Feldman

Si vous êtes particulièrement préoccupé par la taille du code et/ou les performances (également pour l'analyse WCET, si vous en avez besoin), je pense que ce sera probablement l'une des solutions les plus transparentes (pour la recherche et la suppression d'éléments):

unsigned int l=0, removed=0;

for( unsigned int i=0; i<count; i++ ) {
    if( array[i] != to_remove )
        array[l++] = array[i];
    else
        removed++;
}

count -= removed;
0
JosephH

Programming Hub a fourni de manière aléatoire un extrait de code qui/en fait réduit réduit la longueur d'un tableau

for (i = position_to_remove; i < length_of_array; ++i) {
        inputarray[i] = inputarray[i + 1];
}

Je ne sais pas si c'est un comportement qui n'a été ajouté que plus tard. Cela fait l'affaire cependant.

0
MichaelJP