Introduction aux algorithmes de la bibliothèque STL (programmation compétitive)

01 Mar 2022 01 Mar 2022 1809 vues ESSADDOUKI Mostafa 8 min de lecture
Introduction et syntaxe de base
1 Introduction au langage C++ 2 Entrée-sortie en C++ - cin et cout 3 Inférence de type avec le mot-clé auto en C++ 4 Classe std::string et les chaînes de caractères en C++ 5 Les structures conditionnelles (if et switch) en C++ (C++17 et C++20) 6 Les boucles en C++ (C++17 et C++20) 7 La gestion des fichiers en C++
Pointeurs et fonctions
8 Introduction aux pointeurs en C++ - Déclaration et interêts 9 Les références en C++ - déclaration et interêts 10 Les tableaux en C++ - Déclaration et interêts 11 Introduction aux fonctions en C++ 12 Passer des arguments à une fonction en C++ 13 Déclarer un paramètre const en C++ 14 Les fonctions Lambda en C++ 15 Fonctions utiles (Mathématiques et caractères) en C++
Programmation OO
16 Classes et objets en C++ 17 Spécificateurs d'accès en C++ 18 Constructeurs et destructeur d'une classe en C++ 19 Fonctions membres en C++ 20 Membres statiques d'une classe en C++ 21 Fonctions en ligne en C++ - inline 22 Fonctions et classes amies en C++ - friend 23 Surcharge des fonctions en C++ 24 Surcharge des opérateurs en C++ 25 Héritage en C++ 26 La gestion d'exceptions en C++ : déclaration, utilisation et personnalisation 27 fonctions et classes templates en C++ 28 Les nouveautés C++20 pour améliorer les templates en C++
Structures de données
29 Introduction aux structures de données 30 Les structures en C++ et la différence avec les structures en C 31 Les listes chaînées en C++ 32 Les piles en C++ 33 File d'attente en C++ 34 Arbre binaire de recherche : définition et mise en oeuvre en C++
La bibliothèque standard (STL)
35 Introduction à la bibliothèque de Template Standard STL 36 Les itérateurs en C++ - définition, déclaration et exemples 37 La classe array en C++ (bibliothèque STL) <array> 38 La classe vector de la bibliothèque STL <vector> 39 La classe deque en C++ ( Bibliothèque STL) 40 La classe list en C++ (bibliothèque STL) <list> 41 La classe stack (Pile) en C++ (bibliothèque STL) <stack> 42 La classe queue (File d'attente) en C++ (bibliothèque STL) <queue> 43 La file d'attente prioritaire (classe priority_queue) - Bibliothèque STL 44 Les ensembles en C++ (Classe set <set> - Bibliothèque STL) 45 Les dictionnaires en C++ : Classe map (Bibliothèque STL) 46 Introduction aux algorithmes de la bibliothèque STL (programmation compétitive) 47 Tri et méthodes associées en C++ - Bibliothèque STL 48 Recherche dichotomique et méthodes associées en C++ - Bibliothèque STL 49 Appliquer un prédicat ou une fonction aux éléments d'une séquence en C++ - Bibliothèque STL 50 Recherche dans une séquence et méthodes associées en C++ - Bibliothèque STL

Introduction aux algorithmes de la STL

Qu'est-ce qu'un algorithme ?

Un algorithme est une procédure de résolution d'une classe de problèmes. La STL contient une multitude d'algorithmes que vous pouvez utiliser dans vos programmes.

Pourquoi utiliser les algorithmes STL ?

Étant donné que de nombreuses personnes très intelligentes ont consacré beaucoup de temps à s'assurer que ces algorithmes sont corrects et efficaces, vous ne devriez généralement pas essayer, par exemple, d'écrire votre propre algorithme de tri.

L'utilisation d'algorithmes de la bibliothèque STL permet d'économiser du temps, des efforts, du code et est très fiable.

Fonctionnement

STL fournit différents types d'algorithmes qui peuvent être implémentés sur n'importe quel conteneur à l'aide d'itérateurs. Ainsi, nous n'avons plus besoin de définir des algorithmes complexes, mais nous utilisons simplement les fonctions intégrées fournies par la bibliothèque d'algorithmes STL.

L'en-tête <algorithm> définit une collection de fonctions spécialement conçues pour être utilisées sur des collections.

Qu'est-ce qu'une collection ?

Une collection est une séquence d'objets accessible via des itérateurs ou des pointeurs, comme un tableau ou une instance de certains des conteneurs STL (vector, deque, list, etc.).

Notez cependant que les algorithmes fonctionnent via des itérateurs directement sur les valeurs, n'affectant en aucune façon la structure de tout conteneur possible (cela n'affecte jamais la taille ou l'allocation de stockage du conteneur).

Types d'algorithmes

Catégorie 1

Algorithmes de tri

sort, stable_sort, partial_sort, nth_element, etc.

Catégorie 2

Algorithmes de recherche dichotomique

binary_search, lower_bound, upper_bound, equal_range

Catégorie 3

Algorithmes en lecture seule

find, find_if, count, for_each, all_of, any_of, none_of

Catégorie 4

Algorithmes de lecture-écriture

copy, fill, generate, transform, replace, remove

Catégorie 5

Algorithmes numériques

accumulate, partial_sum, adjacent_difference, iota

Catégorie 6

Minimum et maximum

min, max, minmax, min_element, max_element

Politiques d'exécution (C++17 et ultérieur)

Algorithmes parallèles

Certains algorithmes, ceux que l'on appelle communément algorithmes parallèles, peuvent diviser un problème afin que des entités indépendantes puissent travailler simultanément sur différentes parties du problème.

De nombreux algorithmes STL vous permettent de spécifier le parallélisme avec une politique d'exécution. Une politique d'exécution indique le parallélisme autorisé pour un algorithme.

Du point de vue de la STL, un algorithme peut être exécuté :

  • Séquentiellement : une seule entité travaille sur le problème à la fois.
  • En parallèle : de nombreuses entités travaillent de concert pour résoudre le problème.

De plus, les algorithmes parallèles peuvent être :

  • Vectorisés : permettent aux entités d'effectuer des travaux dans un ordre non spécifié, permettant même à une seule entité de travailler simultanément sur plusieurs parties du problème.
  • Non vectorisés : ordre d'exécution plus contraint.
Attention

Un algorithme qui nécessite une synchronisation entre les entités est généralement non vectorisable car la même entité peut tenter d'acquérir un verrou plusieurs fois, entraînant un blocage.

Les trois politiques d'exécution

Trois politiques d'exécution existent dans l'en-tête <execution> :

PolitiqueDescriptionUtilisation
std::execution::seqExécution séquentielle (non parallèle)Comportement par défaut
std::execution::parExécution parallèle (multi-thread)Algorithmes parallélisables
std::execution::par_unseqExécution parallèle et vectoriséeAlgorithmes pouvant être vectorisés
Valeur par défaut

Pour les algorithmes qui prennent en charge une politique d'exécution, la valeur par défaut est seq, ce qui signifie que vous devez opter pour le parallélisme et les avantages de performances associés.

Remarque importante

La norme C++ ne précise pas la signification précise de ces politiques d'exécution car différentes plates-formes gèrent le parallélisme différemment.

Lorsque vous fournissez une politique d'exécution non séquentielle, vous déclarez simplement que "cet algorithme peut être parallélisé en toute sécurité".

Exemple d'utilisation des politiques d'exécution

   
Algorithmes avec politique d'exécution C++17
#include <algorithm>
#include <execution>
#include <vector>

int main() {
    std::vector<int> v = {9, 4, 1, 5, 7, 3, 8, 2, 6};
    
    // Tri séquentiel (explicite)
    std::sort(std::execution::seq, v.begin(), v.end());
    
    // Tri parallèle
    std::sort(std::execution::par, v.begin(), v.end());
    
    // Tri parallèle et vectorisé
    std::sort(std::execution::par_unseq, v.begin(), v.end());
    
    return 0;
}

Explication :

  • std::execution::seq : version classique, une seule thread.
  • std::execution::par : le compilateur peut paralléliser le tri sur plusieurs threads.
  • std::execution::par_unseq : permet en plus la vectorisation (instructions SIMD).

Avantages des algorithmes STL

Fiabilité

Les algorithmes STL sont testés et éprouvés par des milliers de développeurs. Ils sont corrects et robustes.

Performance

Optimisés par des experts, ils offrent souvent les meilleures performances possibles (tri en O(N log N), etc.).

Réutilisabilité

Fonctionnent avec tous les conteneurs STL via les itérateurs. Un même algorithme fonctionne sur vector, deque, list, etc.

Lisibilité

Le code utilisant les algorithmes STL est plus expressif et plus facile à comprendre que des boucles manuelles.

Parallélisme intégré

Depuis C++17, possibilité d'utiliser le parallélisme simplement en ajoutant une politique d'exécution.

Sécurité

Moins de risques d'erreurs (dépassements, off-by-one) par rapport à des implémentations manuelles.

 Exercice pratique

Identifier le bon en-tête

 Niveau : Débutant

Pour chacun des algorithmes suivants, indiquez quel en-tête il faut inclure et à quelle catégorie il appartient :

  1. std::sort()
  2. std::find()
  3. std::accumulate()
  4. std::lower_bound()
  5. std::min()
  6. std::for_each()

Question bonus : Que faut-il ajouter pour utiliser la version parallèle de std::sort() ?

Points clés à retenir
  • Les algorithmes STL sont des fonctions prêtes à l'emploi, testées et optimisées.
  • Ils sont définis principalement dans l'en-tête <algorithm> (et <numeric> pour les algorithmes numériques).
  • Ils fonctionnent sur des collections via des itérateurs, indépendamment du type de conteneur.
  • Six grandes catégories : tri, recherche dichotomique, lecture seule, lecture-écriture, numérique, min/max.
  • Depuis C++17, on peut spécifier une politique d'exécution pour le parallélisme.
  • Trois politiques : seq (séquentiel), par (parallèle), par_unseq (parallèle et vectorisé).
  • L'utilisation d'algorithmes STL rend le code plus fiable, lisible et performant.
  • Il est généralement déconseillé de réinventer la roue en implémentant ses propres algorithmes de base.

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.