Algorithmes et structures de données en Swift : en pratique
Swift est un langage de programmation puissant et intuitif créé par Apple pour le développement sous iOS, macOS, watchOS et tvOS. Cependant, connaître la syntaxe et les frameworks n'est que la moitié du succès. Pour écrire des applications efficaces, rapides et évolutives, il est essentiel de comprendre le fonctionnement des algorithmes et des structures de données. Dans cet article, nous analyserons les concepts clés à l'aide d'exemples concrets de code en Swift. Vous apprendrez à implémenter une pile, une file d'attente, des algorithmes de tri et une recherche binaire, et où ces connaissances sont appliquées dans le développement réel.
Pile (Stack) en Swift : LIFO en action
Une pile est une collection fonctionnant selon le principe "dernier arrivé, premier sorti" (LIFO). Imaginez une pile d'assiettes : vous prenez uniquement celle du dessus. Sous iOS, la pile est utilisée par exemple pour la navigation (UINavigationController) ou pour annuler des actions (Undo).
Implémentons une pile en Swift à l'aide de génériques :
struct Stack<Element> { private var elements: [Element] = [] mutating func push(_ element: Element) { elements.append(element) } @discardableResult mutating func pop() -> Element? { return elements.popLast() } func peek() -> Element? { return elements.last } var isEmpty: Bool { return elements.isEmpty } var count: Int { return elements.count }}
// Exemple d'utilisationvar stack = Stack<String>()stack.push("Premier")stack.push("Deuxième")stack.push("Troisième")
print(stack.pop()!) // Troisièmeprint(stack.peek()!) // DeuxièmeOù est-ce utilisé ? Dans les applications pour afficher l'historique de navigation, dans les analyseurs syntaxiques (vérification des parenthèses), dans les algorithmes de parcours de graphes (DFS).
File d'attente (Queue) : FIFO pour le traitement des tâches
La file d'attente fonctionne selon le principe "premier arrivé, premier sorti" (FIFO). Comme une file d'attente dans un magasin : le premier arrivé est le premier servi. En Swift, la file d'attente est souvent utilisée pour la gestion des tâches (DispatchQueue), le traitement des requêtes réseau ou les animations.
Implémentation de base d'une file d'attente :
struct Queue<Element> { private var elements: [Element] = [] mutating func enqueue(_ element: Element) { elements.append(element) } @discardableResult mutating func dequeue() -> Element? { return isEmpty ? nil : elements.removeFirst() } func front() -> Element? { return elements.first } var isEmpty: Bool { return elements.isEmpty } var count: Int { return elements.count }}
// Exemple d'utilisationvar queue = Queue<Int>()queue.enqueue(1)queue.enqueue(2)queue.enqueue(3)
print(queue.dequeue()!) // 1print(queue.front()!) // 2Problème de performance : removeFirst() sur un tableau a une complexité O(n), car tous les éléments sont décalés. Pour des performances élevées, utilisez ContiguousArray ou une file d'attente double (deque). Dans les projets réels, Apple recommande DispatchQueue pour le multithreading.
Algorithmes de tri : du tri à bulles au tri rapide
Le tri est l'une des opérations les plus courantes. Swift dispose d'une méthode intégrée sort(), mais comprendre les mécanismes internes vous aidera à choisir l'algorithme optimal pour une tâche spécifique.
Tri à bulles (Bubble Sort) — O(n²)
Algorithme simple mais lent. Utile pour l'apprentissage, mais pas pour la production.
func bubbleSort(_ array: inout [Int]) { guard array.count > 1 else { return } for i in 0..<array.count { var swapped = false for j in 0..<(array.count - 1 - i) { if array[j] > array[j + 1] { array.swapAt(j, j + 1) swapped =