Introduction à l'algorithmique 14 - Le tri rapide

Bonjour à tous! Comme prévu aujourd'hui on va voir un autre algorithme de tri, plus performant que le tri à bulles: il s'agit du "tri rapide" (aussi appelé "Quick sort").

Cet algorithme est un peu plus exotique que celui du tri à bulles, il fait appel à plusieurs notions importantes: notamment la récursivité. Si vous n'êtes pas encore à l'aise avec ce concept, je vous invite à revoir <a title="Fonctions récursives" href="https://www.demily-clement.com/2013-10-30-introduction-a-lalgorithmique-11-les-fonctions-recursives.html">ce billet</a>.

Le principe de cet algorithme est de placer un "pivot", puis de faire passer les valeurs plus petites que ce pivot à gaucheet de faire passer les valeurs plus grandes à droitede celui-ci.

On appellera cette étape le partitionnement du tableau. Cette étape est répétée récursivement, sur tous les sous-tableaux! "diviser pour régner"

Pseudo-code de la fonction principale:

DéBUT
tab <- [5, 6, 42, 1, 5, 2, 121, 9, 8, 7, 3, 12, 0, 38, 33, 25, 23, 87, 96]
  ECRIRE "Voici le tableau a trier", tab
  ECRIRE "Voici le tableau trié", QUICK_SORT(tab, 1, COMPTER(tab))
FIN

Pseudo-code de la fonction PARTITIONNER:

ENTRER REFERENCE tab, index_debut, taille
  pivot <- tab[index_debut]
  index_gauche <- p - 1
  index_droite <- taille + 1
  boucler <- 1
  TANTQUE boucler = 1 FAIRE
    RéPéTER
      index_droite <- index_droite - 1
    JUSQU'à tab[index_droite] <= pivot
    RéPéTER
      index_gauche <- index_gauche + 1
    JUSQU'à tab[index_gauche] >= pivot
    SI index_gauche < index_droite ALORS
      tmp <- tab[index_gauche]
      tab[index_gauche] <- tab[index_droite]
      tab[index_droite] <- tmp
    SINON
      boucler <- 0
    FINSI
  FINTANTQUE
RETOURNER index_droite

Comme expliqué plus haut, le principe de l'algorithme réside en partie dans cette fonction.

J'aimerais juste revenir sur le mot-clé REFERENCE. Vous avez du le remarquer: les paramètres des fonctions ne gardent pas les modifications que l'on fait dans le corps de la fonction. Les paramètres sont donc des variables copiéesdepuis la fonction principale. (dans ce cas)

Le seul moyen que l'on connaissait jusqu'à présent pour récupérer des informations d'une fonction était par la valeur de retour.

Le mot-clé REFERENCE sert à contrer ce problème, maintenant toutes modifications sur la variable "tab" sera répercutée partout dans l'algorithme.

Cet aparté fait, on peut revenir à la suite de l'algorithme!

Pseudo-code de la fonction QUICK_SORT:

ENTRER tab, index_debut, taille
  SI index_debut < taille ALORS
    index_droite <- PARTITIONNER(tab, index_debut, taille)
    QUICK_SORT(tab, index_debut, index_droite)
    QUICK_SORT(tab, index_droite + 1, taille)
  FINSI
RETOURNER tab

J'ai essayé de donner un nom clair à mes variables, afin que ça soit le plus simple possible à comprendre.

Je vous conseille une fois de plus de regarder l'exécution pas à pas pour bien tout comprendre.

Un mot sur la complexité algorithmique du tri rapide:

  • Pour le meilleurs des cas (tableau trié): O(n)
  • Pour un cas moyen: O(nlog(n))
  • Pour le pire des cas: O(n²)

En vérité, la complexité algorithmique varie beaucoup selon la manière de la sélection du pivot: pour une sélection arbitraire, la complexité algorithmique tend plus vers le O(n²). En revanche, pour un pivot aléatoire ou un pivot optimal, la complexité algorithmique passe en O(nlog(n)).

La récursivité est certainement l'une des notions les plus délicates à appréhender pour les débutants. C'est un peu "mystique" aux premières utilisations, mais à force de pratique on prend conscience du plein potentiel de cette technique!

Je vous propose de voir demain un problème algorithmique très connu!

A demain!

Tags

  • algorithmique

Cet article à été posté le