Insertion en place☘
Exercice 1☘
On aimerait maintenant écrire une fonction insertion qui ne renvoie pas une nouvelle liste. On veut donc écrire une fonction (avec effet de bord) qui modifie la liste donnée en argument.
def insertion(tab, valeur):
"""
tab -- liste d'entiers,
précondition: liste est triée en ordre croissant
valeur -- entier
Modifie tab en insérant valeur dans tab
de telle façon que tab soit encore triée en ordre croissant
après ajout de valeur.
(renvoie None)
"""
>>> A = [2, 4, 5]
>>> insertion(A, 1)
>>> A
[1, 2, 4, 5]
>>> B = [2, 4, 5]
>>> insertion(B, 4)
>>> B
[2, 4, 4, 5]
>>> C = [2, 4, 5]
>>> insertion(C, 9)
>>> C
[2, 4, 5, 9]
Proposer un code satisfaisant la demande.
Aide 1
On pourra utiliser la fonction déjà vue ci-dessous:
def rechercheIndice(tab, valeur):
"""
tab -- liste d'entiers,
précondition: tab triée en ordre croissant
valeur -- entier
renvoie le plus petit indice i tel que tab[i] >= valeur
et renvoie len(tab) si un tel indice n'existe pas.
"""
for indice, element in enumerate(tab):
if element >= valeur: return indice
return len(tab)
Aide 2: un descriptif possible
- On calcule l'indice auquel placer valeur (avec
rechercheIndicePivot
). - On ajoute une "place" en fin de liste.
- On remonte d'un rang tous les éléments >=
valeur
(ce sont ceux qui ont un indice supérieur ou égal à l'indice calculé pour la valeur à insérer). - On place valeur.
Solution
Un code possible:
def rechercheIndice(tab, valeur):
"""
tab -- liste d'entiers, précondition: tab triée en ordre croissant
valeur -- entier
renvoie le plus petit indice i tel que tab[i] >= valeur
et renvoie len(tab) si un tel indice n'existe pas.
"""
for indice, element in enumerate(tab):
if element >= valeur: return indice
return len(tab)
def insertion(tab, valeur):
"""
tab -- liste d'entiers,
précondition: liste est triée en ordre croissant
valeur -- entier
Modifie tab en insérant valeur dans tab
de telle façon que tab soit encore triée en ordre croissant
après ajout de valeur.
"""
lg = len(tab) # nombre initial d'éléments
# on calcule l'indice auquel placer le nouvel élément:
indice_pivot = rechercheIndice(tab, valeur)
# on ajoute une "place" en fin de liste:
tab.append(0)
# on remonte d'un rang dans la liste tous les éléments >= valeur
# càd les éléments d'indices entre indice_pivot et lg-1:
for k in range(lg-1, indice_pivot-1, -1):
tab[k+1] = tab[k]
# on place valeur dans le "trou" ainsi créé:
tab[indice_pivot] = valeur
Testez...
Exercice 2☘
On suppose maintenant que l'on dispose d'une liste dont les k premiers éléments (d'indices entre 0 et k-1) sont triés en ordre croissant.
Et on aimerait qu'après appel à une nouvelle fonction insertion
les k+1 premiers éléments (ceux
d'indices entre 0 et k) soient triés en ordre croissant.
En d'autres termes, l'élément "valeur" des fonctions précédentes est l'élément d'indice k de la liste et
il s'agit de le placer correctement.
def rechercheIndicePivot(tab, k):
"""
tab -- liste d'entiers,
k -- entier, 0 < k < len(tab)
précondition: tab[0..k-1] est triée en ordre croissant
renvoie le plus petit indice i ( 0 <= i <= k-1)
tel que tab[i] >= tab[k]
et renvoie k si un tel indice n'existe pas.
"""
def insertion(tab, k):
"""
tab -- liste d'entiers,
k -- entier, 0 < k < len(tab)
précondition: tab[0..k-1] est triée en ordre croissant
Modifie tab, en sortie:
- tab contient les mêmes éléments qu'en entrée
- tab[0..k] est triée en ordre croissant
- Chaque élément de tab[k+1..] est inchangé.
"""
Exemple d'utilisation:
>>> A = [2, 4, 5, 1, -2]
>>> insertion(A, 3)
>>> A
[1, 2, 4, 5, -2]
>>> A = [2, 4, 5, 4, -2]
>>> insertion(A, 3)
>>> A
[2, 4, 4, 5, -2]
>>> A = [2, 4, 5, 9, -2]
>>> insertion(A, 3)
>>> A
[2, 4, 5, 9, -2]
Important
Attention, le second paramètre k n'est plus, comme dans les exercices précédents, la valeur à placer mais l'indice de la valeur à placer.
A vous: adapter les fonctions rechercheIndicePivot
et insertion
des exercices précédents
à la situation proposée ici.
Un code possible
def rechercheIndicePivot(tab, k):
"""
tab -- liste d'entiers,
k -- entier, 0 < k < len(tab)
précondition: tab[0..k-1] est triée en ordre croissant
renvoie le plus petit indice i ( 0 <= i <= k-1)
tel que tab[i] >= tab[k]
et renvoie k si un tel indice n'existe pas.
"""
valeur = tab[k]
for indice in range(0, k):
if tab[indice] >= valeur: return indice
return k
def insertion(tab, k):
"""
tab -- liste d'entiers,
k -- entier, 0 < k < len(tab)
précondition: tab[0..k-1] est triée en ordre croissant
Modifie tab, en sortie:
- tab contient les mêmes éléments qu'en entrée
- tab[0..k] est triée en ordre croissant
- Chaque élément de tab[k+1..] est inchangé.
>>> A = [2, 4, 5, 1, -2]
>>> insertion(A, 3)
>>> A
[1, 2, 4, 5, -2]
>>> A = [2, 4, 5, 4, -2]
>>> insertion(A, 3)
>>> A
[2, 4, 4, 5, -2]
>>> A = [2, 4, 5, 9, -2]
>>> insertion(A, 3)
>>> A
[2, 4, 5, 9, -2]
"""
valeur = tab[k]
# on calcule l'indice où placer valeur:
indicePivot = rechercheIndicePivot(tab, k)
# on remonte d'un rang tous les éléments >= valeur:
for j in range(k-1, indicePivot-1, -1):
tab[j+1] = tab[j]
# on place valeur à sa nouvelle position:
tab[indicePivot] = valeur