Algorithmes et structures de données en JavaScript (Node.js) : du débutant au professionnel
Chaque développeur JavaScript rencontre tôt ou tard la nécessité de comprendre en profondeur les algorithmes et les structures de données. Que vous écriviez du frontend avec React ou du backend avec Node.js, savoir comment organiser et traiter efficacement les données est une compétence clé. Dans cet article, nous allons examiner les structures de données de base et les algorithmes populaires avec des exemples pratiques en JavaScript pour l'environnement Node.js.
Pourquoi étudier les algorithmes et les structures de données ?
Les algorithmes et les structures de données sont le fondement sur lequel repose toute application. Un choix approprié de structure de données peut accélérer l'exécution d'un programme des dizaines de fois. Par exemple, la recherche d'un élément dans un tableau de 10 000 éléments peut nécessiter jusqu'à 10 000 opérations, alors que dans une table de hachage, une seule opération suffit. Comprendre ces principes aide à :
- Écrire un code plus performant
- Utiliser efficacement la mémoire
- Réussir les entretiens techniques
- Comprendre le fonctionnement interne des bibliothèques et frameworks populaires
Structures de données principales en JavaScript
Tableaux (Arrays)
Les tableaux sont la structure de données la plus courante en JavaScript. Ils stockent les éléments dans un ordre séquentiel et permettent un accès par index en O(1). Dans Node.js, les tableaux sont particulièrement utiles pour travailler avec des flux de données.
// Exemple de travail avec les tableaux dans Node.jsconst numbers = [5, 2, 9, 1, 5, 6];
// Ajout d'un élément à la finnumbers.push(10); // [5, 2, 9, 1, 5, 6, 10]
// Suppression du dernier élémentconst last = numbers.pop(); // 10
// Recherche d'un élémentconst index = numbers.findIndex(num => num === 9); // 2
// Filtrageconst filtered = numbers.filter(num => num > 5); // [9, 6]
console.log(`Résultat du filtrage : ${filtered}`);Pile (Stack)
La pile fonctionne selon le principe LIFO (Last In, First Out). C'est une structure idéale pour les tâches nécessitant un accès au dernier élément ajouté : historique des actions (undo/redo), vérification des parenthèses, parcours de graphes.
class Stack { constructor() { this.items = []; }
push(element) { this.items.push(element); }
pop() { if (this.isEmpty()) return null; return this.items.pop(); }
peek() { if (this.isEmpty()) return null; return this.items[this.items.length - 1]; }
isEmpty() { return this.items.length === 0; }
size() { return this.items.length; }}
// Exemple : vérification de la validité des parenthèsesfunction isValidParentheses(str) { const stack = new Stack(); const pairs = { '(': ')', '{': '}', '[': ']' };
for (let char of str) { if (pairs[char]) { stack.push(char); } else { const last = stack.pop(); if (pairs[last] !== char) return false; } }
return stack.isEmpty();}
console.log(isValidParentheses("({[]})")); // trueconsole.log(isValidParentheses("({[})")); // falseFile d'attente (Queue)
La file d'attente fonctionne selon le principe FIFO (First In, First Out). Elle est indispensable pour traiter les tâches dans l'ordre de leur arrivée : planificateurs de tâches, files de messages, BFS (parcours en largeur).
class Queue { constructor() { this.items = {}; this.front = 0; this.rear = 0; }
enqueue(element) { this.items[this.rear] = element; this.rear++; }
dequeue() { if (this.isEmpty()) return null; const item = this.items[this.front]; delete this.items[this.front]; this.front++; return item; }
isEmpty() { return this.front === this.rear; }
size() { return this.rear - this.front; }}
// Exemple : simulation d'une file d'impressionconst printQueue = new Queue();printQueue.enqueue("document1.pdf");printQueue.enqueue("document2.pdf");printQueue.enqueue("photo.jpg");
while (!printQueue.isEmpty()) {