Algorithmes et structures de données en C# : le fondement d'un code .NET efficace
Dans le développement moderne sur la plateforme .NET, la connaissance des algorithmes et des structures de données est une compétence obligatoire pour créer des applications performantes et évolutives. Que vous écriviez des services web avec ASP.NET Core, des applications de bureau avec WPF ou des solutions mobiles avec Xamarin, le choix correct de la structure de données influence directement la vitesse d'exécution du programme et la consommation mémoire. Dans cet article, nous analyserons les structures de données et algorithmes clés en langage C#, en accompagnant chaque section d'exemples de code pratiques.
1. Structures de données de base en C# : tableaux et listes
Commençons par les fondamentaux. En C#, il existe plusieurs types intégrés pour stocker des collections, et comprendre leur fonctionnement interne est crucial.
Tableaux (Array)
Un tableau est une séquence fixe d'éléments du même type. Il offre l'accès le plus rapide par index (O(1)), mais ne permet pas de modifier sa taille après sa création.
int[] numbers = new int[5] { 10, 20, 30, 40, 50 };// Accès par indexint thirdElement = numbers[2]; // 30// Modification d'un élémentnumbers[3] = 100;Utilisez les tableaux lorsque le nombre d'éléments est connu à l'avance et ne changera pas (par exemple, pour stocker des constantes ou des tampons fixes).
Liste (List<T>)
List<T> est un tableau dynamique. Il s'étend automatiquement lors de l'ajout de nouveaux éléments. En interne, il utilise un tableau ordinaire qui est recréé lorsque la capacité est dépassée.
List<string> fruits = new List<string>();fruits.Add("Pomme");fruits.Add("Banane");fruits.Add("Orange");Console.WriteLine(fruits.Count); // 3fruits.RemoveAt(1); // Supprime "Banane"List<T> est un choix universel pour la plupart des tâches nécessitant un accès séquentiel et des changements fréquents de taille de collection.
2. Pile et file d'attente : principes LIFO et FIFO
Ces deux structures de données implémentent des règles strictes d'ajout et d'extraction d'éléments. Elles sont indispensables pour l'analyse d'expressions, le traitement de tâches différées et l'implémentation d'algorithmes de parcours.
Pile (Stack<T>)
La pile fonctionne selon le principe "dernier arrivé, premier sorti" (LIFO). Dans .NET, la pile est implémentée comme une collection générique.
Stack<int> stack = new Stack<int>();stack.Push(1);stack.Push(2);stack.Push(3);
int top = stack.Pop(); // 3int peek = stack.Peek(); // 2 (sans suppression)Exemple concret : vérification de la validité des parenthèses dans une chaîne ou implémentation du bouton "Précédent" dans un navigateur.
File d'attente (Queue<T>)
La file d'attente suit le principe "premier arrivé, premier sorti" (FIFO). C'est un choix idéal pour traiter des tâches dans l'ordre de leur arrivée.
Queue<string> queue = new Queue<string>();queue.Enqueue("Tâche 1");queue.Enqueue("Tâche 2");queue.Enqueue("Tâche 3");
string task = queue.Dequeue(); // "Tâche 1"string nextTask = queue.Peek(); // "Tâche 2"Les files d'attente sont activement utilisées dans les patterns Producer-Consumer, pour le traitement de messages et dans les systèmes de journalisation.
3. Arbres et algorithmes récursifs en C#
Les arbres sont des structures hiérarchiques où chaque nœud peut avoir plusieurs nœuds enfants. Une place particulière est occupée par les arbres binaires de recherche (BST), qui assurent une recherche, une insertion et une suppression rapides (O(log n) en moyenne).
Implémentation d'un arbre binaire de recherche
public class TreeNode{ public int Value; public TreeNode Left; public TreeNode Right;
public TreeNode(int value) { Value = value; }}
public class BinarySearchTree{ public TreeNode Root;
public void Insert(int value) { Root = InsertRec(Root, value); }
private TreeNode InsertRec(TreeNode root, int value) { if (root == nu