QuickSort

L’un des algorithmes de tri les plus répandus est QuickSort. C’est un algorithme « diviser pour régner » qui choisit itérativement un pivot dans le tableau, scinde le tableau en 3 parties – les éléments plus petits, égaux et plus grands que le pivot – et répète ce processus jusqu’à ce que le tableau soit entièrement trié.
Donc, à chaque itération :
  1. On choisit un élément pivot dans le tableau
  1. On déplace les éléments plus petits à gauche du pivot
  1. On déplace les éléments plus grands à droite du pivot
  1. On regroupe tous les éléments égaux au pivot au milieu
  1. On répète ce processus sur les parties gauche et droite
def quicksort(a):
    if len(a) <= 1:
        return a
    pivot = a[len(a) // 2]
    left = [x for x in a if x < pivot]
    middle = [x for x in a if x == pivot]
    right = [x for x in a if x > pivot]
    return quicksort(left) + middle + quicksort(right)
Cette implémentation de QuickSort utilise des tableaux supplémentaires pour les parties left, middle et right. Nous pouvons le rendre “in place” (en place) en modifiant le code pour utiliser des indices et réorganiser les éléments directement dans le tableau.
def quicksort(a, start, end):
    if start >= end:                    # Aucun élément à trier
        return

    pivot = a[start]                    # Choisir un pivot
    l, r = start + 1, end               # Trier a[start+1 ... end]
    while l <= r:                       # Tant qu'il reste des éléments dans la plage
        if a[l] < pivot:                # si a[l] < pivot => on ne touche pas a[i]
            l += 1                      # Incrémenter le pointeur gauche
        else:                           # sinon déplacez a[l] vers la fin
            a[l], a[r] = a[r], a[l]     # Échanger a[l] et a[r] -> déplacer vers la fin
            r -= 1                      # Décrémenter le pointeur droit

    a[start], a[r] = a[r], a[start]     # Échanger le pivot avec a[r]
    quicksort(a, start, r - 1)          # Trier a[start ... r-1]
    quicksort(a, r + 1, end)            # Trier a[r+1 ... end]
Vous avez peut-être remarqué que le choix du pivot différait dans ces deux implémentations. L’algorithme QuickSort n’impose pas de règle stricte pour le choix du pivot. Il existe plusieurs façons de le choisir. En voici quelques-unes :
  1. Premier élément : a[start], comme dans la deuxième implémentation
  1. Dernier élément : a[end]
  1. Élément du milieu : a[(start + end + 1) // 2]
  1. Élément aléatoire : choisir n’importe quel élément dans a[start ... end]
  1. Élément médian : choisir la médiane du segment courant. Cela garantit une répartition égale entre left et right, mais requiert une implémentation plus sophistiquée.

Faisons une simulation de l’algorithme sur plusieurs tableaux :
[4, 1, -1, 0, 2, 8]
  1. quicksort(a, 0, 5) → pivot = 4 [4, 1, -1, 0, 2, 8]
    1. l=1, r=5a[l] = 1 < pivot ⇒ l += 1
    2. l=2, r=5a[l] = -1 < pivot ⇒ l += 1
    3. l=3, r=5a[l] = 0 < pivot ⇒ l += 1
    4. l=4, r=5a[l] = 2 < pivot ⇒ l += 1
    5. l=5, r=5a[l] = 8 ≥ pivot ⇒ swap a[l] and a[r], r -= 1
    6. swap a[start] and a[r][2, 1, -1, 0, 4, 8]
    7. quicksort(a, 0, 3) and quicksort(a, 5, 5)
  1. quicksort(a, 0, 3) → pivot = 2 [2, 1, -1, 0, 4, 8]
    1. l=1, r=3a[l] = 1 < pivot ⇒ l += 1
    2. l=2, r=3a[l] = -1 < pivot ⇒ l += 1
    3. l=3, r=3a[l] = 0 < pivot ⇒ l += 1
    4. swap a[start] and a[r][0, 1, -1, 2, 4, 8]
    5. quicksort(a, 0, 2) and quicksort(a, 3, 3)
  1. quicksort(a, 0, 2) → pivot = 0 [0, 1, -1, 2, 4, 8]
    1. l=1, r=2a[l] = 1 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [0, -1, 1, 2, 4, 8]
    2. l=1, r=1a[l] = -1 < pivot ⇒ l += 1
    3. swap a[start] and a[r][-1, 0, 1, 2, 4, 8]
    4. quicksort(a, 0, 0) and quicksort(a, 2, 2)
  1. [-1, 0, 1, 2, 4, 8]
[4, 5, 3, 4, 4, 8, 4, 1, 2, 9, 7, 4, -1]
  1. quicksort(a, 0, 12) → pivot = 4 [4, 5, 3, 4, 4, 8, 4, 1, 2, 9, 7, 4, -1]
    1. l=1, r=12a[l] = 5 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, 5, 3, 4, 4, 8, 4, 1, 2, 9, 7, 4, -1]
    2. l=1, r=11a[l] = -1 < pivot ⇒ l += 1
    3. l=2, r=11a[l] = 3 < pivot ⇒ l += 1
    4. l=3, r=11a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 4, 4, 8, 4, 1, 2, 9, 7, 4, 5]
    5. l=3, r=10a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 4, 4, 8, 4, 1, 2, 9, 7, 4, 5]
    6. l=3, r=9a[l] = 7 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 7, 4, 8, 4, 1, 2, 9, 4, 4, 5]
    7. l=3, r=8a[l] = 9 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 9, 4, 8, 4, 1, 2, 7, 4, 4, 5]
    8. l=3, r=7a[l] = 2 < pivot ⇒ l += 1
    9. l=4, r=7a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 2, 4, 8, 4, 1, 9, 7, 4, 4, 5]
    10. l=4, r=6a[l] = 1 < pivot ⇒ l += 1
    11. l=5, r=6a[l] = 8 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 2, 1, 8, 4, 4, 9, 7, 4, 4, 5]
    12. l=5, r=5a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [4, -1, 3, 2, 1, 4, 8, 4, 9, 7, 4, 4, 5]
    13. swap a[start] and a[r][1, -1, 3, 2, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    14. quicksort(a, 0, 3) and quicksort(a, 5, 12)
  1. quicksort(a, 0, 3) → pivot = 1 [1, -1, 3, 2, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    1. l=1, r=3a[l] = -1 < pivot ⇒ l += 1
    2. l=2, r=3a[l] = 3 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [1, -1, 3, 2, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    3. l=2, r=2a[l] = 2 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [1, -1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    4. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    5. quicksort(a, 0, 0) and quicksort(a, 2, 3)
  1. quicksort(a, 2, 3) → pivot = 2 [-1, 1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    1. l=3, r=3a[l] = 3 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    2. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    3. quicksort(a, 2, 1) and quicksort(a, 3, 3)
  1. quicksort(a, 5, 12) → pivot = 4 [-1, 1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    1. l=6, r=12a[l] = 8 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 8, 4, 9, 7, 4, 4, 5]
    2. l=6, r=11a[l] = 5 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 5, 4, 9, 7, 4, 4, 8]
    3. l=6, r=10a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 4, 9, 7, 4, 5, 8]
    4. l=6, r=9a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 4, 9, 7, 4, 5, 8]
    5. l=6, r=8a[l] = 7 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 7, 4, 9, 4, 4, 5, 8]
    6. l=6, r=7a[l] = 9 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 9, 4, 7, 4, 4, 5, 8]
    7. l=6, r=6a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 9, 7, 4, 4, 5, 8]
    8. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 4, 9, 7, 4, 4, 5, 8]
    9. quicksort(a, 5, 4) and quicksort(a, 6, 12)
  1. quicksort(a, 6, 12) → pivot = 4 [-1, 1, 2, 3, 4, 4, 4, 9, 7, 4, 4, 5, 8]
    1. l=7, r=12a[l] = 9 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 9, 7, 4, 4, 5, 8]
    2. l=7, r=11a[l] = 8 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 8, 7, 4, 4, 5, 9]
    3. l=7, r=10a[l] = 5 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 5, 7, 4, 4, 8, 9]
    4. l=7, r=9a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 4, 7, 4, 5, 8, 9]
    5. l=7, r=8a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 4, 7, 4, 5, 8, 9]
    6. l=7, r=7a[l] = 7 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 7, 4, 4, 5, 8, 9]
    7. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 4, 7, 4, 4, 5, 8, 9]
    8. quicksort(a, 6, 5) and quicksort(a, 7, 12)
  1. quicksort(a, 7, 12) → pivot = 7 [-1, 1, 2, 3, 4, 4, 4, 7, 4, 4, 5, 8, 9]
    1. l=8, r=12a[l] = 4 < pivot ⇒ l += 1
    2. l=9, r=12a[l] = 4 < pivot ⇒ l += 1
    3. l=10, r=12a[l] = 5 < pivot ⇒ l += 1
    4. l=11, r=12a[l] = 8 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 7, 4, 4, 5, 8, 9]
    5. l=11, r=11a[l] = 9 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 7, 4, 4, 5, 9, 8]
    6. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 4, 5, 4, 4, 7, 9, 8]
    7. quicksort(a, 7, 9) and quicksort(a, 11, 12)
  1. quicksort(a, 7, 9) → pivot = 5 [-1, 1, 2, 3, 4, 4, 4, 5, 4, 4, 7, 9, 8]
    1. l=8, r=9a[l] = 4 < pivot ⇒ l += 1
    2. l=9, r=9a[l] = 4 < pivot ⇒ l += 1
    3. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 9, 8]
    4. quicksort(a, 7, 8) and quicksort(a, 10, 9)
  1. quicksort(a, 7, 8) → pivot = 4 [-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 9, 8]
    1. l=8, r=8a[l] = 4 ≥ pivot ⇒ swap a[l] and a[r], r -= 1 [-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 9, 8]
    2. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 9, 8]
    3. quicksort(a, 7, 6) and quicksort(a, 8, 8)
  1. quicksort(a, 11, 12) → pivot = 9 [-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 9, 8]
    1. l=12, r=12a[l] = 8 < pivot ⇒ l += 1
    2. swap a[start] and a[r][-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 8, 9]
    3. quicksort(a, 11, 11) and quicksort(a, 13, 12)
  1. [-1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 7, 8, 9]
Le temps d’exécution moyen de l’algorithme QuickSort est . Cependant, selon la façon dont on choisit le pivot, le temps d’exécution peut devenir quadratique .
🤔 Pouvez-vous imaginer un exemple où l’algorithme effectuerait opérations si l’on choisit toujours start comme pivot ?

Challenge

Étant donné une liste de n entiers et q pivots, le but est de déplacer tous les éléments plus petits que le pivot à gauche, et tous les éléments plus grands à droite de cet élément pivot, tout en conservant ensemble tous ceux qui lui sont égaux (regroupés à la suite des nombres plus petits et à l’intérieur des nombres plus grands).

Entrée

La première ligne de l’entrée contient un seul entier n (1 ≤ n ≤ 100 000).
La ligne suivante contient une liste de n entiers séparés par des espaces ().
La troisième ligne contient un seul entier q (1 ≤ q ≤ 10).
La ligne suivante contient une liste de n entiers séparés par des espaces (1 ≤ ≤ n) qui représentent l’indice de l’élément pivot.

Sortie

Pour chacun des q pivots, le programme doit afficher le tableau résultant après avoir effectué le réarrangement. S’il existe plusieurs réponses possibles, le programme peut en imprimer n’importe laquelle.

Exemples

Entrée
Sortie
7 1 8 0 3 4 -2 4 3 4 2 5
1 0 -2 3 4 4 8 -2 0 1 3 4 4 8 -2 0 1 3 4 4 8
 

Constraints

Time limit: 2 seconds

Memory limit: 512 MB

Output limit: 10 MB

To check your solution you need to sign in
Sign in to continue