Skip to content

Le drapeau

Énoncé

On va revenir sur l'exercice du pivot déjà traité dans une séance précédente en implantant une variante très connue dite du « drapeau » (souvent hollandais mais ça marche avec plein d'autres !)

La différence avec l'algorithme du pivot est qu'à la fin de la boucle, le tableau doit être divisé en 3 zones :

  • la partie de gauche contenant les éléments strictement inférieurs au pivot ;
  • la partie du milieu contenant les éléments égaux au pivot ;
  • la partie de droite contenant les éléments strictement supérieurs au pivot.

La fonction à écrire a pour prototype drapeau(tab, idx_pivot) et renvoie deux indices :

  • deb_piv est l'indice de la première case contenant une valeur égale au pivot ;
  • fin_piv est l'indice de la dernière case contenant une valeur égale au pivot.

On travaillera sur un tableau statique et en place sans allouer de tableau intermédiaire. On pourra utiliser le programme principal suivant pour tester notre fonction.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env python3
"""
  Pivot
"""

from random import randint

TAILLE = 20

def echanger(tab, idx1, idx2):
    """
      Echange tab[idx1] et tab[idx2]
    """
    tmp = tab[idx1]
    tab[idx1] = tab[idx2]
    tab[idx2] = tmp


def main():
    """
      Fonction principale
    """
    tab = [randint(0, 10) for _ in range(TAILLE)]
    idx_pivot = randint(0, TAILLE - 1)
    print("Tableau initial :", tab)
    print("Indice du pivot : ", idx_pivot, ", valeur du pivot : ",
          tab[idx_pivot], sep="")
    print("Drapeau en place :")
    deb_piv, fin_piv = drapeau(tab, idx_pivot)
    print("  indices du pivot : de", deb_piv, "à", fin_piv)
    print("  tableau réorganisé :", tab[0:deb_piv], tab[deb_piv:fin_piv + 1], tab[fin_piv + 1:])

main()

Correction

Cliquez ici pour révéler la correction.

drapeau.py :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python3
"""
  Pivot
"""

from random import randint

TAILLE = 20

def echanger(tab, idx1, idx2):
    """
      Echange tab[idx1] et tab[idx2]
    """
    tmp = tab[idx1]
    tab[idx1] = tab[idx2]
    tab[idx2] = tmp

def drapeau(tab, idx_pivot):
    """
      Version 3 : drapeau en place
    """
    val_pivot = tab[idx_pivot]
    echanger(tab, 0, idx_pivot)
    idx_pivot = 0
    prem = 1
    dern = len(tab) - 1
    while prem <= dern:
        if tab[prem] < val_pivot:
            echanger(tab, prem, idx_pivot)
            idx_pivot += 1
            prem += 1
        elif tab[prem] == val_pivot:
            prem += 1
        else:
            echanger(tab, prem, dern)
            dern -= 1
    return idx_pivot, dern

def main():
    """
      Fonction principale
    """
    tab = [randint(0, 10) for _ in range(TAILLE)]
    idx_pivot = randint(0, TAILLE - 1)
    print("Tableau initial :", tab)
    print("Indice du pivot : ", idx_pivot, ", valeur du pivot : ",
          tab[idx_pivot], sep="")
    print("Drapeau en place :")
    deb_piv, fin_piv = drapeau(tab, idx_pivot)
    print("  indices du pivot : de", deb_piv, "à", fin_piv)
    print("  tableau réorganisé :", tab[0:deb_piv], tab[deb_piv:fin_piv + 1], tab[fin_piv + 1:])

main()

invariant du drapeau