Utilisation des algorithmes STL en C++ pour la manipulation de conteneurs

La bibliothèque standard C++ (STL) fournit un riche ensemble d'algorithmes pour la manipulation efficace des conteneurs. Ces algorithmes sont classés en plusieurs catégories en fonction de leur comportement : ceux qui ne modifient pas les séquences, ceux qui les modifient, les algorithmes de tri, les algorithmes de tas, les algorithmes de recherche de minimum/maximum, et les algorithmes numériques.

  1. Algorithmes de séquence non modifiants

Ces algorithmes inspectent les éléments d'un conteneur sans en altérer le contenu.

1.1 Recherche d'éléments

  • std::find(debut, fin, valeur) : Recherche la première occurrence de valeur dans la plage [debut, fin). Retourne un itérateur vers l'élément trouvé, ou fin si l'élément n'est pas présent.
  • std::find_if(debut, fin, predicat) : Recherche la première occurrence d'un élément satisfaisant le predicat (une fonction ou un foncteur retournant un booléen).
  • std::find_end(debut1, fin1, debut2, fin2) : Recherche la dernière occurrence de la sous-séquence définie par [debut2, fin2) dans la séquence [debut1, fin1).

std::vector<int> nombres = {10, 30, 50, 70, 90};

// Rechercher la valeur 50
auto it_trouve = std::find(nombres.begin(), nombres.end(), 50);
if (it_trouve != nombres.end()) {
   std::cout << "Trouvé : " << *it_trouve << std::endl; // Affiche : Trouvé : 50
}

// Rechercher le premier élément supérieur à 60
auto it_condition = std::find_if(nombres.begin(), nombres.end(), [](int x){ return x > 60; });
if (it_condition != nombres.end()) {
   std::cout << "Premier > 60 : " << *it_condition << std::endl; // Affiche : Premier > 60 : 70
}

// Rechercher une sous-séquence
std::vector<int> sous_sequence = {30, 50};
auto it_sous = std::find_end(nombres.begin(), nombres.end(), sous_sequence.begin(), sous_sequence.end());
if (it_sous != nombres.end()) {
   // Note : find_end retourne un itérateur vers le début de la dernière occurrence
   std::cout << "Sous-séquence trouvée commençant à l'index : " << (it_sous - nombres.begin()) << std::endl; // Affiche : Sous-séquence trouvée commençant à l'index : 1
}
 </int></int>

1.2 Comptage d'éléments

  • std::count(debut, fin, valeur) : Compte le nombre d'occurrences de valeur.
  • std::count_if(debut, fin, predicat) : Compte le nombre d'éléments satisfaisant le predicat.

std::vector<int> valeurs = {11, 22, 33, 22, 44, 22};
int compte_22 = std::count(valeurs.begin(), valeurs.end(), 22); // compte_22 vaut 3
int compte_pairs = std::count_if(valeurs.begin(), valeurs.end(), [](int x){ return x % 2 == 0; }); // compte_pairs vaut 4
 </int>

1.3 Parcours d'éléments

  • std::for_each(debut, fin, fonction) : Applique une fonction à chaque élément de la plage [debut, fin).

std::vector<int> chiffres = {1, 2, 3, 4, 5};
std::for_each(chiffres.begin(), chiffres.end(), [](int& elem){ elem *= 2; });
// chiffres contient maintenant {2, 4, 6, 8, 10}
 </int>

1.4 Comparaison de séquences

  • std::equal(debut1, fin1, debut2) : Vérifie si la plage [debut1, fin1) est égale à la plage commençant à debut2 et de même taille.
  • std::mismatch(debut1, fin1, debut2) : Trouve la première paire d'éléments non égaux entre les plages [debut1, fin1) et [debut2, ...). Retourne une paire d'itérateurs vers les éléments non correspondants.

std::vector<int> seq_a = {1, 2, 3};
std::vector<int> seq_b = {1, 2, 4};
std::vector<int> seq_c = {1, 2, 3, 4};

bool sont_egales = std::equal(seq_a.begin(), seq_a.end(), seq_b.begin()); // sont_egales vaut false

auto denom_pair = std::mismatch(seq_a.begin(), seq_a.end(), seq_c.begin());
if (denom_pair.first != seq_a.end()) {
   // Dans cet exemple, seq_a et seq_c correspondent sur les 3 premiers éléments.
   // Si seq_a était {1, 2, 4} et seq_c {1, 2, 3}, denom_pair.first pointerait sur 4 et denom_pair.second sur 3.
}
 </int></int></int>

1.5 Vérification de prédicats sur des plages

  • std::all_of(debut, fin, predicat) : Retourne true si tous les éléments satisfont le predicat.
  • std::any_of(debut, fin, predicat) : Retourne true si au moins un élément satisfait le predicat.
  • std::none_of(debut, fin, predicat) : Retourne true si aucun élément ne satisfait le predicat.

std::vector<int> ensemble = {2, 4, 6, 8};
bool tous_pairs = std::all_of(ensemble.begin(), ensemble.end(), [](int x){ return x % 2 == 0; }); // true
bool y_a_impair = std::any_of(ensemble.begin(), ensemble.end(), [](int x){ return x % 2 != 0; }); // false
bool aucun_negatif = std::none_of(ensemble.begin(), ensemble.end(), [](int x){ return x < 0; }); // true
 </int>
  1. Algorithmes de séquence modifiants

Ces algorithmes altèrent le contenu des conteneurs sur lesquels ils opèrent.

2.1 Copie d'éléments

  • std::copy(debut_source, fin_source, debut_destination) : Copie les éléments de la plage source vers la destination. La destination doit avoir suffisamment d'espace alloué.
  • std::copy_if(debut_source, fin_source, debut_destination, predicat) : Copie uniquement les éléments qui satisfont le predicat.

std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination(source.size());

// Copier tous les éléments
std::copy(source.begin(), source.end(), destination.begin()); // destination contient {1, 2, 3, 4, 5}

// Copier uniquement les éléments pairs dans un nouveau vecteur
std::vector<int> pairs;
std::copy_if(source.begin(), source.end(), std::back_inserter(pairs), [](int x){ return x % 2 == 0; }); // pairs contient {2, 4}
 </int></int></int>

L'utilisation de std::back_inserter permet d'ajouter des éléments à la fin du conteneur de destination sans nécessiter d'allocation préalable.

2.2 Transformation d'éléments

  • std::transform(debut_source, fin_source, debut_destination, operation) : Applique une operation unaire à chaque élément de la plage source et stocke le résultat dans la plage de destination.
  • std::transform(debut_source1, fin_source1, debut_source2, debut_destination, operation) : Applique une operation binaire aux éléments des deux plages sources et stocke le résultat dans la destination.

std::vector<int> nombres = {1, 2, 3};
std::vector<int> carres(nombres.size());
std::transform(nombres.begin(), nombres.end(), carres.begin(), [](int x){ return x * x; }); // carres contient {1, 4, 9}

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {4, 5, 6};
std::vector<int> somme(v1.size());
std::transform(v1.begin(), v1.end(), v2.begin(), somme.begin(), [](int x, int y){ return x + y; }); // somme contient {5, 7, 9}
 </int></int></int></int></int>

2.3 Remplacement d'éléments

  • std::replace(debut, fin, ancienne_valeur, nouvelle_valeur) : Remplace toutes les occurrences de ancienne_valeur par nouvelle_valeur.
  • std::replace_if(debut, fin, predicat, nouvelle_valeur) : Remplace les éléments satisfaisant le predicat par nouvelle_valeur.
  • std::replace_copy(debut_source, fin_source, debut_destination, ancienne_valeur, nouvelle_valeur) : Copie les éléments de la source vers la destination, en remplaçant ancienne_valeur par nouvelle_valeur. Le conteneur source n'est pas modifié.

std::vector<int> donnees = {1, 2, 3, 2, 5};

std::replace(donnees.begin(), donnees.end(), 2, 20); // donnees contient {1, 20, 3, 20, 5}

std::replace_if(donnees.begin(), donnees.end(), [](int x){ return x > 10; }, 0); // donnees contient {1, 0, 3, 0, 5}

std::vector<int> resultat_copie;
std::replace_copy(donnees.begin(), donnees.end(), std::back_inserter(resultat_copie), 3, 300); // resultat_copie contient {1, 0, 300, 0, 5}
 </int></int>

2.4 Suppression d'éléments (logique)

  • std::remove(debut, fin, valeur) : Déplace tous les éléments égaux à valeur vers la fin de la plage [debut, fin) et retourne un itérateur vers le nouveau "fin logique" des éléments valides. Ne supprime pas réellement les éléments du conteneur.
  • std::remove_if(debut, fin, predicat) : Similaire à remove, mais utilise un predicat pour identifier les éléments à "supprimer".

Ces fonctions sont généralement utilisées en combinaison avec la méthode erase du conteneur pour supprimer physiquement les éléments déplacés.


std::vector<int> liste = {1, 2, 3, 2, 4};

// Déplacer les 2 vers la fin
auto nouveau_fin = std::remove(liste.begin(), liste.end(), 2); // liste est maintenant {1, 3, 4, ?, ?} (les ? sont les anciens 2)

// Supprimer physiquement les éléments invalides
liste.erase(nouveau_fin, liste.end()); // liste contient {1, 3, 4}

// Suppression des éléments pairs en une seule opération
std::vector<int> liste2 = {1, 2, 3, 4, 5};
liste2.erase(std::remove_if(liste2.begin(), liste2.end(), [](int x){ return x % 2 == 0; }), liste2.end()); // liste2 contient {1, 3, 5}
 </int></int>

2.5 Suppression des doublons consécutifs

  • std::unique(debut, fin) : Supprime les éléments dupliqués adjacents dans la plage [debut, fin). Comme remove, il retourne le nouvel itérateur de fin logique et ne modifie pas la taille du conteneur. Il doit être combiné avec erase.

std::vector<int> vec_doublons = {1, 1, 2, 2, 3, 3, 3, 4, 5};
auto dernier_unique = std::unique(vec_doublons.begin(), vec_doublons.end());
vec_doublons.erase(dernier_unique, vec_doublons.end()); // vec_doublons contient {1, 2, 3, 4, 5}
 </int>

2.6 Inversion et Rotation

  • std::reverse(debut, fin) : Inverse l'ordre des éléments dans la plage [debut, fin).
  • std::rotate(debut, milieu, fin) : Effectue une rotation de la plage [debut, fin) de sorte que l'élément pointé par milieu devienne le premier élément.

std::vector<int> v_a_inverser = {1, 2, 3, 4, 5};
std::reverse(v_a_inverser.begin(), v_a_inverser.end()); // v_a_inverser contient {5, 4, 3, 2, 1}

std::vector<int> v_a_rotater = {1, 2, 3, 4, 5};
// Déplace l'élément à l'index 2 (valeur 3) au début
std::rotate(v_a_rotater.begin(), v_a_rotater.begin() + 2, v_a_rotater.end()); // v_a_rotater contient {3, 4, 5, 1, 2}
 </int></int>

2.7 Mélange aléatoire

  • std::shuffle(debut, fin, generateur) : Réorganise aléatoirement les éléments dans la plage [debut, fin) en utilisant le generateur de nombres aléatoires fourni. (Nécessite C++11 ou plus)

#include <random>
#include <algorithm> // Nécessaire pour std::shuffle

std::vector<int> desordonner = {1, 2, 3, 4, 5};
std::random_device rd; // Génère une graine aléatoire matérielle
std::mt19937 g(rd()); // Mersenne Twister, un générateur de nombres pseudo-aléatoires de haute qualité
std::shuffle(desordonner.begin(), desordonner.end(), g); // desordonner est maintenant dans un ordre aléatoire
 </int>
  1. Algorithmes de tri et apparentés

3.1 Tri

  • std::sort(debut, fin) : Trie la plage [debut, fin). C'est un tri rapide (généralement introsort), non stable, avec une complexité temporellle moyenne de O(N log N).
  • std::stable_sort(debut, fin) : Trie la plage de manière stable, préservant l'ordre relatif des éléments égaux. Sa complexité est également O(N log N), mais il peut utiliser plus de mémoire.
  • std::partial_sort(debut, milieu, fin) : Trie seulement les milieu - debut plus petits éléments de la plage [debut, fin) et les place dans l'ordre dans la sous-plage [debut, milieu).

std::vector<int> elements = {5, 3, 1, 4, 2};
std::sort(elements.begin(), elements.end()); // elements trié : {1, 2, 3, 4, 5}

// Tri décroissant
std::sort(elements.begin(), elements.end(), std::greater<int>()); // elements trié : {5, 4, 3, 2, 1}

// Tri stable basé sur une clé
std::vector<std::pair<int, char>> paires = {{1, 'b'}, {2, 'a'}, {1, 'c'}, {2, 'd'}};
std::stable_sort(paires.begin(), paires.end(), [](const auto& a, const auto& b){ return a.first < b.first; });
// paires trié : {{1, 'b'}, {1, 'c'}, {2, 'a'}, {2, 'd'}} (ordre relatif préservé pour les clés égales)

std::vector<int> data = {5, 3, 1, 4, 2, 6};
// Place les 3 plus petits éléments triés au début
std::partial_sort(data.begin(), data.begin() + 3, data.end());
// data contient {1, 2, 3, ?, ?, ?} où les '?' sont les éléments restants non triés.
 </int></int></int>

3.2 Tri partiel avancé

  • std::nth_element(debut, n, fin) : Réorganise la plage [debut, fin) de telle sorte que l'élément à la position n soit celui qui serait à cette position si la plage était entièrement triée. Tous les éléments avant n sont inférieurs ou égaux à l'élément à n, et tous les éléments après n sont supérieurs ou égaux. C'est un tri partiel non garanti en O(N) en moyenne.

std::vector<int> nums = {5, 3, 1, 4, 2, 6};
// Assure que l'élément à l'index 2 (3ème plus petit) est à sa place correcte
std::nth_element(nums.begin(), nums.begin() + 2, nums.end());
// Après l'appel, nums[2] contient la valeur 3. Les éléments avant nums[2] sont <= 3,
// et ceux après nums[2] sont >= 3. L'ordre interne de ces sous-plages n'est pas garanti.
 </int>

3.3 Recherche binaire et bornes

Ces algorithmes nécessitent que la plage soit préalablement triée.

  • std::binary_search(debut, fin, valeur) : Vérifie si valeur est présente dans la plage triée [debut, fin). Retourne true ou false.
  • std::lower_bound(debut, fin, valeur) : Retourne un itérateur vers le premier élément de la plage qui n'est pas inférieur à valeur (c'est-à-dire, >= valeur).
  • std::upper_bound(debut, fin, valeur) : Retourne un itérateur vers le premier élément de la plage qui est strictement supérieur à valeur.

std::vector<int> triee = {1, 3, 3, 5, 7};

bool existe = std::binary_search(triee.begin(), triee.end(), 3); // existe vaut true

auto borne_inf = std::lower_bound(triee.begin(), triee.end(), 3); // pointe vers le premier 3 (index 1)
std::cout << "Index borne inférieure pour 3 : " << (borne_inf - triee.begin()) << std::endl;

auto borne_sup = std::upper_bound(triee.begin(), triee.end(), 3); // pointe vers 5 (index 3)
std::cout << "Index borne supérieure pour 3 : " << (borne_sup - triee.begin()) << std::endl;
 </int>

3.4 Fusion de séquences triées

  • std::merge(debut1, fin1, debut2, fin2, debut_destination) : Fusionne deux plages triées [debut1, fin1) et [debut2, fin2) en une seule plage triée dans la destination. La destination doit avoir une capacité suffisante.

std::vector<int> v_trie1 = {1, 3, 5};
std::vector<int> v_trie2 = {2, 4, 6};
std::vector<int> fusionnee(v_trie1.size() + v_trie2.size());

std::merge(v_trie1.begin(), v_trie1.end(), v_trie2.begin(), v_trie2.end(), fusionnee.begin());
// fusionnee contient {1, 2, 3, 4, 5, 6}
 </int></int></int>
  1. Algorithmes de tas

La STL fournit des algorithmes pour manipuler des séquences comme des tas binaires (généralement des tas maximaux par défaut).

  • std::make_heap(debut, fin) : Transforme la plage [debut, fin) en un tas.
  • std::push_heap(debut, fin) : Ajoute le dernier élément de la plage (qui a été préalablement ajouté au conteneur) dans le tas existant couvrant [debut, fin-1).
  • std::pop_heap(debut, fin) : Déplace le plus grand élément (la racine du tas) du tas [debut, fin) vers la position fin-1, et réorganise le reste [debut, fin-1) en un tas valide.
  • std::sort_heap(debut, fin) : Trie la plage qui représente un tas.

std::vector<int> tas_data = {4, 1, 3, 2, 5};
std::make_heap(tas_data.begin(), tas_data.end()); // tas_data ressemble à {5, 4, 3, 2, 1} (structure de tas max)

tas_data.push_back(6); // Ajout de l'élément
std::push_heap(tas_data.begin(), tas_data.end()); // tas_data ressemble à {6, 4, 5, 2, 1, 3}

std::pop_heap(tas_data.begin(), tas_data.end()); // Le plus grand (6) est déplacé à la fin
int max_element = tas_data.back(); // max_element vaut 6
tas_data.pop_back(); // Retire 6 du vecteur

std::sort_heap(tas_data.begin(), tas_data.end()); // tas_data est maintenant trié : {1, 2, 3, 4, 5}
 </int>
  1. Algorithmes de minimum/maximum

5.1 Minimum et Maximum de deux valeurs

  • std::min(a, b) : Retourne le plus petit de a et b.
  • std::max(a, b) : Retourne le plus grand de a et b.
  • Il existe également des surcharges pour les listes d'initialisation (depuis C++11).

int val1 = 5, val2 = 3;
int minimum = std::min(val1, val2); // minimum vaut 3
int maximum = std::max(val1, val2); // maximum vaut 5

auto min_liste = std::min({4, 2, 8, 5, 1}); // min_liste vaut 1
auto max_liste = std::max({4, 2, 8, 5, 1}); // max_liste vaut 8
 

5.2 Minimum et Maximum dans une plage

  • std::min_element(debut, fin) : Retourne un itérateur vers le plus petit élément dans la plage [debut, fin).
  • std::max_element(debut, fin) : Retourne un itérateur vers le plus grand élément dans la plage [debut, fin).

std::vector<int> vals = {3, 1, 4, 2, 5};
auto it_min = std::min_element(vals.begin(), vals.end()); // it_min pointe vers 1
auto it_max = std::max_element(vals.begin(), vals.end()); // it_max pointe vers 5
 </int>

5.3 Minimum et Maximum simultanés

  • std::minmax_element(debut, fin) : Retourne une paire d'itérateurs, le premier pointant vers le plus petit élément et le second vers le plus grand élément de la plage. (Nécessite C++11 ou plus)

std::vector<int> vals = {3, 1, 4, 2, 5};
auto minmax_it = std::minmax_element(vals.begin(), vals.end());
// minmax_it.first pointe vers 1, minmax_it.second pointe vers 5
 </int>
  1. Algorithmes numériques (dans <numeric>)

6.1 Accumulation

  • std::accumulate(debut, fin, valeur_initiale) : Calcule la somme des éléments de la plage [debut, fin), en commençant par valeur_initiale.
  • std::accumulate(debut, fin, valeur_initiale, operation_binaire) : Permet d'utiliser une opération binaire personnalisée (par défaut, l'addition).

#include <numeric>

std::vector<int> chiffres = {1, 2, 3, 4, 5};
int somme = std::accumulate(chiffres.begin(), chiffres.end(), 0); // somme vaut 15

// Calculer le produit
int produit = std::accumulate(chiffres.begin(), chiffres.end(), 1, std::multiplies<int>()); // produit vaut 120
 </int>

6.2 Produit scalaire

  • std::inner_product(debut1, fin1, debut2, valeur_initiale) : Calcule le produit scalaire de deux plages. La plage 1 est [debut1, fin1) et la plage 2 commence à debut2 et a la même taille que la plage 1.

std::vector<int> vec_a = {1, 2, 3};
std::vector<int> vec_b = {4, 5, 6};
// Calcule (1*4 + 2*5 + 3*6)
int produit_scalaire = std::inner_product(vec_a.begin(), vec_a.end(), vec_b.begin(), 0); // produit_scalaire vaut 32
 </int></int>

6.3 Remplissage séquentiel

  • std::iota(debut, fin, valeur_debut) : Remplit la plage [debut, fin) avec des valeurs consécutives commençant à valeur_debut. (Nécessite C++11 ou plus)

std::vector<int> suite(5);
std::iota(suite.begin(), suite.end(), 10); // suite contient {10, 11, 12, 13, 14}
 </int>

6.4 Somme partielle

  • std::partial_sum(debut_source, fin_source, debut_destination) : Calcule les sommes partielles des éléments de la plage source et les stocke dans la plage destination.

std::vector<int> source_somme = {1, 2, 3, 4, 5};
std::vector<int> dest_somme(source_somme.size());
std::partial_sum(source_somme.begin(), source_somme.end(), dest_somme.begin()); // dest_somme contient {1, 3, 6, 10, 15}
 </int></int>

6.5 Différence adjacente

  • std::adjacent_difference(debut_source, fin_source, debut_destination) : Calcule la différence entre chaque élément et le précédent dans la plage source et stocke les résultats dans la plage destination. Le premier élément est copié tel quel.

std::vector<int> source_diff = {1, 2, 3, 4, 5};
std::vector<int> dest_diff(source_diff.size());
std::adjacent_difference(source_diff.begin(), source_diff.end(), dest_diff.begin()); // dest_diff contient {1, 1, 1, 1, 1} (car 2-1=1, 3-2=1, etc.)
 </int></int>
  1. Autres algorithmes utiles

7.1 Génération de séquences

  • std::generate(debut, fin, generateur) : Remplit la plage [debut, fin) en appelant répétitivement la fonction generateur.
  • std::generate_n(debut_destination, nombre, generateur) : Génère nombre éléments en utilisant le generateur et les écrit à partir de debut_destination.

std::vector<int> generateur_vec(5);
int compteur = 0;
std::generate(generateur_vec.begin(), generateur_vec.end(), [&compteur](){ return compteur++; }); // generateur_vec contient {0, 1, 2, 3, 4}

std::vector<int> generateur_n_vec(5);
int debut_val = 10;
std::generate_n(generateur_n_vec.begin(), 3, [&debut_val](){ return debut_val++; }); // generateur_n_vec contient {10, 11, 12, 0, 0} (les deux derniers éléments ne sont pas modifiés)
 </int></int>

7.2 Inclusion de plages

  • std::includes(debut1, fin1, debut2, fin2) : Vérifie si la plage triée [debut1, fin1) contient tous les éléments de la plage triée [debut2, fin2).

std::vector<int> plage_principale = {1, 2, 3, 4, 5};
std::vector<int> sous_ensemble = {2, 4};
bool contient = std::includes(plage_principale.begin(), plage_principale.end(), sous_ensemble.begin(), sous_ensemble.end()); // contient vaut true
 </int></int>

7.3 Opérations sur ensembles

Ces algorithmes nécessitent que les deux plages d'entrée soient triées.

  • std::set_union : Calcule l'union des deux ensembles.
  • std::set_intersection : Calcule l'intersection des deux ensembles.
  • std::set_difference : Calcule la différence entre le premier et le second ensemble (éléments dans le premier mais pas dans le second).
  • std::set_symmetric_difference : Calcule la différence symétrique (éléments présents dans l'un ou l'autre ensemble, mais pas dans les deux).

std::vector<int> ens1 = {1, 2, 3, 4, 5};
std::vector<int> ens2 = {3, 4, 5, 6, 7};
std::vector<int> resultat;

// Union
std::set_union(ens1.begin(), ens1.end(), ens2.begin(), ens2.end(), std::back_inserter(resultat));
// resultat : {1, 2, 3, 4, 5, 6, 7}

// Intersection
resultat.clear();
std::set_intersection(ens1.begin(), ens1.end(), ens2.begin(), ens2.end(), std::back_inserter(resultat));
// resultat : {3, 4, 5}

// Différence (ens1 - ens2)
resultat.clear();
std::set_difference(ens1.begin(), ens1.end(), ens2.begin(), ens2.end(), std::back_inserter(resultat));
// resultat : {1, 2}

// Différence symétrique
resultat.clear();
std::set_symmetric_difference(ens1.begin(), ens1.end(), ens2.begin(), ens2.end(), std::back_inserter(resultat));
// resultat : {1, 2, 6, 7}
 </int></int></int>
  1. Questions fréquentes

  1. Quelle est la différence entre std::sort et std::stable_sort ?std::sort est généralemetn plus rapide mais n'est pas stable : l'ordre relatif des éléments égaux peut changer. std::stable_sort garantit que l'ordre relatif des éléments égaux est préservé, au prix d'une complexité spatiale potentiellement plus élevée.
  2. Pourquoi std::remove doit-il être utilisé avec container.erase ?std::remove ne supprime pas réellement les éléments ; il les déplace vers la fin de la plage et retourne un itérateur vers le début de cette section "invalide". La taille du conteneur n'est pas modifiée. container.erase est nécessaire pour supprimer physiquement ces éléments de la fin du conteneur et ajuster sa taille.
  3. **Quels algorithmes STL nécessitent que le conteneur soit trié ?**Les algorithmes de recherche binaire (std::binary_search, std::lower_bound, std::upper_bound), les algorithmes de fusion (std::merge) et les algorithmes d'opérations sur ensembles (std::set_union, std::set_intersection, etc.) nécessitent des plages d'entrée triées pour fonctionner correctement et efficacement.

Étiquettes: C++ STL algorithmes Conteneurs manipulation de données

Publié le 15 juin à 04h04