Implémentation des algorithmes de recherche en Swift

Recherche séquentielle

La recherche séquentielle constitue l'approche fondamentale pour localiser un élément dans une collection. Son principe repose sur l'examen successif de chaque élément jusqu'à identifier la cible ou épuiser tous les éléments.

Méthodes d'implémentation

func rechercheLineaire<T: Equatable>(_ collection: [T], _ cible: T) -> Int? {
    for (position, valeur) in collection.enumerated() {
        if valeur == cible {
            return position
        }
    }
    return nil
}

Alternative utilisent les fonctions d'ordre supérieur :

func rechercheLineaire<T: Equatable>(_ collection: [T], _ cible: T) -> Int? {
    return collection.firstIndex { $0 == cible }
}

Analyse de performance

Scénario Complexité temporelle
Meilleur cas O(1)
Cas moyen O(n)
Pire cas O(n)

Domaines d'application

  • Collections de petite taille
  • Données non triées
  • Recherches ponctuelles

Recherche dichotomique

La recherche dichotomique exploite la nature triée des données pour diviser systématiquement l'espace de recherche.

Version itérative

func rechercheDichotomique<T: Comparable>(_ collection: [T], _ cible: T) -> Int? {
    var debut = 0
    var fin = collection.count
    
    while debut < fin {
        let milieu = debut + (fin - debut) / 2
        
        if collection[milieu] == cible {
            return milieu
        } else if collection[milieu] < cible {
            debut = milieu + 1
        } else {
            fin = milieu
        }
    }
    return nil
}

Version récursive

func rechercheDichotomique<T: Comparable>(_ collection: [T], _ cible: T, _ intervalle: Range<Int>) -> Int? {
    guard intervalle.lowerBound < intervalle.upperBound else {
        return nil
    }
    
    let milieu = intervalle.lowerBound + (intervalle.upperBound - intervalle.lowerBound) / 2
    
    if collection[milieu] > cible {
        return rechercheDichotomique(collection, cible, intervalle.lowerBound..<milieu cible="" collection="" else="" if="" milieu="" recherchedichotomique="" return=""></milieu>

Comparaison des approches

Caractéristique Itérative Récursive
Complexité spatiale O(1) O(log n)
Performance Supérieure Inférieure
Lisibilité Modérée Élevée

Optimisations avancées

Recherche par interpolation pour données uniformément distribuées :

func rechercheInterpolation(_ collection: [Int], _ cible: Int) -> Int? {
    var debut = 0
    var fin = collection.count - 1
    
    while debut <= fin && cible >= collection[debut] && cible <= collection[fin] {
        if debut == fin {
            return collection[debut] == cible ? debut : nil
        }
        
        let position = debut + ((cible - collection[debut]) * (fin - debut)) / (collection[fin] - collection[debut])
        
        if collection[position] == cible {
            return position
        } else if collection[position] < cible {
            debut = position + 1
        } else {
            fin = position - 1
        }
    }
    return nil
}

Analyse comparative

Les tests de performance révèlent des différences significatives selon la taille des données :

  • Petites collections : la recherche séquentielle s'avère souvent plus efifcace
  • Grandes colelctions triées : la recherche dichotomique présente un avantage décisif
  • Collections dynamiques : le coût de tri peut contrebalancer les bénéfices de la dichotomie

Stratégie hybride

func rechercheOptimisee<T: Comparable>(_ collection: [T], _ cible: T) -> Int? {
    if collection.count < 50 {
        return collection.firstIndex { $0 == cible }
    } else {
        let collectionTriee = collection.sorted()
        return rechercheDichotomique(collectionTriee, cible)
    }
}

Étiquettes: Swift algorithmes RECHERCHE performance Optimisation

Publié le 27 août à 11h18