Vous avez vu l'année dernière le tri par insertion et le tri par selection et tous les deux avaient une complexité en \(\mathcal{O}\left(n^2\right)\).
A copier dans le cahier.
L'expression "diviser pour régner" en informatique est utilisée pour décrire un algorithme fractionnant un problème, ou des données en éléments plus petits afin de les traiter.
Une utilisation "classique" de "diviser pour régner" est son utilisation sur les listes et avec une récurrence.
Soit tab
un tableau non vide d'entiers triés dans l'ordre croissant et n
un entier.
La fonction chercher
ci-dessous doit renvoyer un indice où la valeur n
apparaît dans tab
si cette valeur y figure et None
sinon.
Les paramètres de la fonction sont :
tab
, le tableau dans lequel s'effectue la recherchen
, l'entier à chercher dans le tableaui
, l'indice de début de la partie du tableau où s'effectue la recherchej
, l'indice de fin de la partie du tableau où s'effectue la rechercheL’algorithme demandé est une recherche dichotomique récursive.
Recopier et compléter le code de la fonction chercher
suivante :
def chercher(tab, n, i, j):
if i < 0 or j > len(tab):
return None
elif i > j:
return None
m = (i + j) // ...
if ... < n:
return chercher(tab, n, ..., ...)
elif ... > n:
return chercher(tab, n, ..., ...)
else:
return ...
L'exécution du code doit donner :
>>> chercher([1, 5, 6, 6, 9, 12], 7, 0, 10)
>>> chercher([1, 5, 6, 6, 9, 12], 7, 0, 5)
>>> chercher([1, 5, 6, 6, 9, 12], 9, 0, 5)
4
>>> chercher([1, 5, 6, 6, 9, 12], 6, 0, 5)
2
Écrire une fonction recherche
qui prend en paramètres un tableau tab
de nombres
entiers triés par ordre croissant et un nombre entier n
, et qui effectue une recherche
dichotomique du nombre entier n
dans le tableau non vide tab
.
Cette fonction doit renvoyer un indice correspondant au nombre cherché s’il est dans le
tableau, -1
sinon.
Exemples :
>>> recherche([2, 3, 4, 5, 6], 5)
3
>>> recherche([2, 3, 4, 6, 7], 5)
-1
A copier dans le cahier.
Le tri par fusion est un algorithme de tri d'une liste qui fonctionne par récurrence à l'aide du principe de diviser pour régner.
Sa complexité est en \(\mathcal{O}\left(n \log(n)\right)\).
Compléter la fonction fusion(liste1,liste2)
, qui prend comme paramètres deux listes triées et qui renvoie une liste triée composée des élements des deux autres.
def fusion(liste1,liste2):
'''
fusion prend deux listes triées et retourne une grand liste triée contenant les éléments des deux autres.
'''
final=[] #liste qui sera retournée
curseur1=0 #curseur de la liste1
curseur2=0 #curseur de la liste2
while ...................................................... : #tant que il reste des éléments non traités dans une des deux listes
if ............... : #le plus petit élément est dans la liste 1
final.append(liste1[curseur1])
curseur1+=1
else: #le plus petit élément est celui de la liste 2
......................
......................
if ......................... : #il reste des éléments dans la liste 2 à traiter
for i in range(curseur2,len(liste2)):
final.append(.......)
else : #il reste des éléments dans la liste 1 à traiter
for i in range(curseur1,len(liste1)):
final.append(.......)
return final
On pourra tester notre fonction fusion
à l'aide des listes suivantes :
listeA=[2,5,7,8,9,11,13,15,19,21,25,29,35,38,39,40,52,69,78,89]
listeB=[3,4,5,7,12,14,15,18,23,30,32,33,34,42,53]
Compléter la fonction tri_par_fusion(liste)
à l'aide de la fonction de l'exercice précédent.
def tri_par_fusion(liste):
if ............ : # Il y a un élément dans la liste ou moins.
return liste
else:
moitie=...... # indice correspondant au milieu de la liste
gauche=tri_par_fusion(.............)
droite=tri_par_fusion(.............)
return fusion(gauche,droite)
A faire dans le cahier.
Ce code a permis de générer les 3 images ci-dessous :
Il peut sembler que les courbes soient similiaires mais :
A copier dans le cahier.
Les tris par insertion et par selection sont de complexités quadratiques en \(\mathcal{O}\left(n^2 \right)\).
Le tri par fusion est de complexité linéarithmique en \(\mathcal{O}\left(n \log(n)\right)\).