Algorithmes et structures de données en Swift : du débutant au professionnel
Swift est un langage de programmation puissant et intuitif d'Apple, utilisé pour développer des applications pour iOS, macOS, watchOS et tvOS. La compréhension des algorithmes et des structures de données est le fondement qui distingue un développeur expérimenté d'un débutant. Dans cet article, nous allons décomposer les concepts clés avec des exemples pratiques en Swift.
1. Structures de données de base en Swift
La bibliothèque standard de Swift fournit plusieurs structures intégrées qui sont à la base de toute application.
Tableaux (Array)
Collection ordonnée d'éléments du même type. Prend en charge l'accès aléatoire par index.
var numbers: [Int] = [10, 20, 30, 40, 50]numbers.append(60)numbers.insert(5, at: 0)print(numbers[2]) // Sortie : 30Dictionnaires (Dictionary)
Collection de paires « clé-valeur » pour une recherche rapide de données par clé unique.
var userScores: [String: Int] = ["Alice": 95, "Bob": 87]userScores["Charlie"] = 92if let score = userScores["Alice"] { print("Score d'Alice : \\(score)")}Ensembles (Set)
Collection non ordonnée d'éléments uniques. Idéal pour vérifier la présence ou supprimer les doublons.
let fruits: Set = ["Pomme", "Banane", "Orange", "Pomme"]print(fruits.count) // Sortie : 3 (doublon supprimé)2. Implémentation de la pile et de la file d'attente en Swift
La pile et la file d'attente sont des structures de données classiques, souvent implémentées à l'aide de tableaux.
Pile (Stack) — LIFO (Last In, First Out)
Les éléments sont ajoutés et supprimés à une seule extrémité.
struct Stack<T> { private var elements: [T] = [] mutating func push(_ value: T) { elements.append(value) } mutating func pop() -> T? { return elements.popLast() } func peek() -> T? { return elements.last }}
var stack = Stack<Int>()stack.push(1)stack.push(2)stack.push(3)print(stack.pop()!) // Sortie : 3File d'attente (Queue) — FIFO (First In, First Out)
Les éléments sont ajoutés à la fin et supprimés du début.
struct Queue<T> { private var elements: [T] = [] mutating func enqueue(_ value: T) { elements.append(value) } mutating func dequeue() -> T? { return elements.isEmpty ? nil : elements.removeFirst() }}
var queue = Queue<String>()queue.enqueue("Premier")queue.enqueue("Second")print(queue.dequeue()!) // Sortie : Premier3. Algorithmes de tri et de recherche
Examinons deux algorithmes fondamentaux utiles dans des projets réels.
Tri rapide (Quick Sort)
Algorithme efficace « diviser pour régner » avec une complexité moyenne de O(n log n).
func quickSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } let pivot = array[array.count / 2] let less = array.filter { $0 < pivot } let equal = array.filter { $0 == pivot } let greater = array.filter { $0 > pivot } return quickSort(less) + equal + quickSort(greater)}
let unsorted = [3, 6, 8, 10, 1, 2, 1]print(quickSort(unsorted)) // Sortie : [1, 1, 2, 3, 6, 8, 10]Recherche binaire (Binary Search)
Fonctionne uniquement sur un tableau trié. Complexité O(log n).
func binarySearch(_ array: [Int], target: Int) -> Int? { var low = 0 var high = array.count - 1 while low <= high { let mid = (low + high) / 2 if array[mid] == target { return mid } else if array[mid] < target { low = mid + 1 } else { high = mid - 1 } } return nil}
let sortedArray = [1, 3, 5, 7, 9, 11]if let index = binarySearch(sortedArray, target: 7) { p