• Aucun résultat trouvé

T.P. 3 : des arbres binaires variés et leurs applications

N/A
N/A
Protected

Academic year: 2022

Partager "T.P. 3 : des arbres binaires variés et leurs applications"

Copied!
6
0
0

Texte intégral

(1)

T.P. 3 : des arbres binaires vari´ es et leurs applications 1 Arbres binaires de recherche

1.1 Ce qu’on doit d´ ej` a savoir sur la recherche d’un mot dans une liste tri´ ee et apr` es ...

Supposons par exemple qu’on veuille constituer et manipuler un lexique anglais/fran¸cais. Un tel lexique sera repr´esent´e en Python par une liste de couples de mots, comme par exemple :

lexique = [(’blue’,’bleu’),(’green’,’vert’),(’red’,’rouge’),(’yellow’,’jaune’)]

On suppose que les mots anglais sont rang´es dans l’ordre du dictionnaire (comme dans l’exemple pr´ec´edent). Cet ordre est l’ordre implant´e en python sur les chaines de caract`eres avec le symbole<.

Notons aussi que pour les couples, python commence par comparer les premi`eres entr´ees.

On suppose donc qu’on dispose d’une variable globale lexiquecomme ci-dessus.

a) Sachant que la liste des mots anglais esttri´eedans l’ordre du dictionnaire, ´ecrire une fonction traduitqui re¸coit un mot anglais en argument (qui est suppos´e ˆetre dans le lexique) et renvoie sa traduction avec une complexit´e en O(log(n))o`unest la longueur du lexique.

N.B.La complexit´elogarithmique demande une m´ethode de dichotomie.

b) Ecriture une fonctioninserequi re¸coit un argument qui est un couple(motanglais, motfrancais) qui permet de rajouter ce couple `a la bonne place dans la variable globalelexique : cette fonction sera de complexit´e lin´eaire.

Le probl`eme : la repr´esentation de notre lexique sous cette forme fait que la fonctioninserea une complexit´e enO(n). Nous allons maintenant pr´esenter une nouvelle fa¸con de coder le lexique, une autre structure de donn´ee, o`u l’insertion, comme la recherche, d’un mot dans le lexique, sera enO(log(n)).

1.2 Pr´ esentation des arbres binaires de recherche

D´efinition math´ematique 1 : un arbre sera pour nous un ensemble de points appel´esnoeuds muni d’une relation pour laquelle chaque noeud a un p`ere et un seul (on repr´esente la relation p`ere fils par une fl`eche), sauf un noeud qui n’a pas de p`ere qu’on appelle la racine. On convient de repr´esenter la racine en haut et les p`eres en dessus de leurs fils.

Si le noeudpest le p`ere du noeudf on dit aussi quef est un fils dep. Les noeuds qui n’ont pas de fils sont appel´esfeuilles.

D´efinition math´ematique 2 : un arbre au sens pr´ec´edent sera ditarbre binairesi chaque p`ere a au plus deux fils, appel´es alors fils droit et fils gauche.

Lien avec notre probl`eme : Chaque noeud sera un ´el´ement de notre ensemble de couples (motanglais,motfrancais). La relation p`ere/fils entre les mots sera d´efinie au niveau des parties motanglais(la partiemotanglaisdu couple est ce qu’on appelle la cl´e d’enregistrement).

(2)

Par exemple, avec un lexique `a quatre mots :

ici la racine sera le couple dontblueest la cl´e, avec deux fils de cl´esredetyellowetreda un fils green

D´efinition 3 : d´efinition informatique d’un arbre binaire, avec son implantation py- thon : un arbre binaire est une structure de donn´ee qui peut ˆetre d´efinie r´ecursivement comme suit : un arbre binaire est :

— soit vide, cod´e comme une liste vide [],

— soit cod´e comme une liste [racine, filsGauche, filsDroit] o`u racine est un couple (motanglais,motfrancais), etfilsDroits etfilsGauche sont deux arbres binaires.

Exemple : Avec Arbrelexique=[(’blue’,’bleu’),filsGauche,filsDroit]o`u filsGauche=[(’red’,’rouge’),[],[(’green’,’vert’),[],[]]] et

filsDroit=[(’yellow’,’jaune’),[],[]], on aura le codage informatique de l’arbre binaire dessin´e ci-dessus.

D´efinition 4 : arbre binairede recherche: un arbre[racine, filsGauche, filsDroit]au sens de la d´efinition 3 est unarbre binaire de recherchesi, et seulement si,

— la cl´e deracineest strictement sup´erieure `a la cl´e de tous les noeuds defilsGauche,

— la cl´e deracineest strictement inf´erieure `a la cl´e de tous les noeuds defilsDroit,

— filsDroitetfilsGauche sont des arbres binaires de recherche.

L’exemple pr´ec´edent ne donne pas un arbre binaire de recherche mais la version modifi´ee sui- vante oui :

1.3 Implantation en python de la fabrication r´ ecursive des arbres bi- naires de recherche... et recherche !

On consid`ere donc des arbres binaires de recherche comme d´efinis au paragraphe pr´ec´edents, dont les noeuds sont des couples(motanglais,motfrancais) que l’on compare pour l’ordre lexi- cographique des mots anglais.

(3)

a) Ecrire trois fonctionsfilsGauche, filsDroit, racinequi prennent en argument un arbre binaire de recherche arbre et renvoie respectivement son fils Gauche, son fils Droit, et sa racine.

b) On veut ´ecrire alors une fonction r´ecursive ajout(element, arbre) qui prend comme ar- gument un ´el´ement i.e. un couple (motanglais,motfrancais) et un arbre binaire (qui au d´epart peut ˆetre vide, ce sera notre cas de base) et qui retourne un nouvel arbre binaire de recherche o`u elementest incorpor´e `aarbre.

N.B.on doit comparer les mots anglais.

Pour cela, le principe est le suivant :

● si le mot anglais de l’´el´ement `a rajouter est plus grand que le mot anglais `a la racine de l’arbre, on construit un arbre binaire en gardant la mˆeme racine, le mˆeme fils gauche, et on se ram`ene au probl`eme de rajouter l’´el´ement au fils droit.

● si le mot anglais de l’´el´ement `a rajouter est plus petit que le mot anglais `a la racine de l’arbre ... `a vous de deviner !

Ecrire la fonction python correspondante ! Par commodit´e pour la suite, on consid´erera aussi le cas o`u le mot qu’on rajoute est d´ej`a pr´esent dans l’arbre : dans ce cas bien sˆur l’arbre ne devra pas ˆetre modifi´e.

c) Appliquer la fonction pr´ec´edente pour fabriquer un arbre binaire de recherche pour notre lexique en ajoutant successivement les ´el´ements de la liste suivante :

lexique = [(’red’,’rouge’),(’blue’,’bleu’),(’yellow’,’jaune’),(’green’,’vert’)]

d) Ecrire enfin une fonction r´ecursivetraduit2(mot,arbre)qui renvoie la traduction d’un mot anglais qui est stock´e dans un arbre binaire de recherche comme pr´ec´edemment.

(On comparera mot `a la (partie anglaise de la) racine de l’arbre, et si ils sont diff´erents, ensuite r´ecursivement soit `a filsDroit soit `a filsGauche..)

1.4 Complexit´ es : arbres binaire ´ equilibr´ es

a) D´efinition : la hauteur (on dit aussi profondeur) d’un noeud de l’arbre est le nombre de g´en´erations qui le s´eparent de la racine de l’arbre. Cette hauteur admet naturellement une d´efinition r´ecursive rigoureuse (laquelle ?)

En d´eduire une fonction r´ecursive hauteur(element, arbre) qui renvoie la hauteur du noeud elementsuppos´e pr´esent dans l’arbre binaire de recherchearbre.

b) Par d´efinition la hauteur de l’arbre est la maximum des hauteurs des ´el´ements. On dira qu’un arbre ayantnnoeuds est´equilibr´essi sa hauteur est minimale parmi tous les arbres ayantn noeuds. Donner en l’expliquant, une relation entre la hauteur hd’un arbre ´equilibr´e et son nombre total de noeudsn.

Le dessin suivant, qui est un cas particulier, devrait suffire pour comprendre !

N.B.Pour les questions qui suivent, on admet qu’on peut toujours ranger nos donn´ees dans un arbre binaire de recherche´equilibr´e1.

c) Justifiez que la fonction traduit2du paragraphe pr´ec´edent, appliqu´ee `a un arbre´equilibr´e, est de complexit´eO(log(n))o`unest le nombre de noeuds de l’arbre.

1. en fait il existe bien des algorithmes pour s’y ramener, en faisant desrotations

(4)

d) La fonctionajoutdu paragraphe pr´ec´edent fabrique-t-elle forc´ement des graphes ´equilibr´es ? e) Montrer en tous cas que si on applique cette fonction ajout a un arbre ´equilibr´e ayant n

noeuds, la complexit´e de l’ajout est enO(log(n)).

Moralit´e : par rapport `a ce qu’on a dit au tout premier paragraphe, les arbres binaires de recherche ´equilibr´es ont l’avantage qu’aussi bien la recherche que l’ajout d’une donn´ee sont en O(log(n)).

2 Une classe python fabriqu´ ee suivant les principes du § 1 : les dictionnaires python

La classe dictionary n’est pas au programme, dans une ´epreuve d’´ecrit on devrait vous la pr´esenter !

a) Au§1, on a expliqu´e (modulo le probl`eme d’´equilibrage des arbres !) comment fabriquer une structure qui permet de g´erer un dictionnaire denmots avec une complexit´e enO(log(n))pour la recherche et l’ajout d’un mot. En python, il existe une structure qui fait exactement cela, la classe dict.

Par exemple dico={’red’: ’rouge’, ’blue’: ’bleu’, ’yellow’ : ’jaune’} sera un dic- tionnaire avec trois entr´ees, les mots en anglais ici seront les cl´es qui servent `a acc´eder aux valeurs qu’elles r´ef´erencent (ici les mots en fran¸cais).

Voici quelques commandes de cette classe :

a={} # cr´eation d’un dictionnaire vide appel´e a

a[’truc’]=12 # cr´eation d’une entr´ee du dictionnaire avec la valeur 12 et `a la cl´e ’truc’

# eh oui c’est exactement ce qu’on ne peut pas faire avec les listes.. pas de out of range ici ! a[’truc’] # va renvoyer la valeur 12.

dico[’red’] # va renvoyer ’rouge’

’yellow’ in dico # va renvoyer True

’black’ in dico # va renvoyer False

Question (exemple) ´ecrire une fonction freq qui prend en param`etre une chaˆıne de ca- ract`eres comme’CABBAA’et renvoie un dictionnaire o`u les lettres sont les cl´es et le nombre d’oc- currence de chaque lettre est la valeur stock´ee pour chaque cl´es. Ainsifreq(’CABBAA’) renverra {’A’: 3, ’B’: 2, ’C’: 1}. Noter qu’il n’y a pasd’ordred´efini entre les cl´es d’un dictionnaire.

b) Quelque pr´ecision sur le parcours des dictionnaires : (i) Avecdicocomme ci-dessus, que donne le code : for a in dico:

print(a)

(ii) Comment faire alors pour voir `a la fois les cl´es et les valeurs qu’elles r´ef´erencent dans le dictionnaire dico ? Cr´eer une fonction ListeCouple qui prend en argument un dictionnaire et renvoie une liste des couples (cl´e,valeur). Par exemple ListeCouple(dico) renverra (`a l’ordre pr`es) :

[(’blue’, ’bleu’), (’red’, ’rouge’), (’yellow’, ’jaune’)]

3 Tri avec la construction d’un arbre binaire de recherche

a) On a vu au §1.3 comment on pouvait transformer une liste en arbre binaire de recherche.

Explicitement, `a l’aide de la fonctionajoutd´efinie dans ce paragraphe, ´ecrire une fonctionABRqui fabrique un tel arbre `a partir d’une liste. Ainsi pour L=[34,2,667,1,4,20],ABR(L)donnera :

[34, [2, [1, [], []], [4, [], [20, [], []]]], [667, [], []]]

b) Expliquer ce que fait alors la fonction suivante, appliqu´ee la variable arbre ci-dessus, et `a la liste videt=[]:

(5)

def parcoursProfondeur(arbre,t):

if arbre!=[]:

t=parcoursProfondeur(filsGauche(arbre),t) t.append(racine(arbre))

t=parcoursProfondeur(filsDroit(arbre),t) return t

En d´eduire une m´ethode pour trier une liste (par exemple une liste de nombres) qui commence par transformer cette liste en arbre binaire de recherche.

4 Les tas et le tri par tas

4.1 La structure de tas : encore un arbre binaire

D´efinition : un tas binaire, ici on dira simplement un tas (en anglaisheap) est un arbre binaire (comme au§1) qui est ordonn´e de sorte que la cl´e d’un noeud est toujours sup´erieure `a la cl´e de ses fils (de sorte que son plus grand ´el´ement est toujours la racine de l’arbre)2.

Du point de vue informatique, on va ici coder simplement ces arbres par un tableau (liste python) de nombres.

Par exemple T=[9,5,6,2,1,5,1,0] codera l’arbre ci- contre. Cet arbre est bien un tas, puisque chaque p`ere a une valeur sup´erieur `a celles de ses fils.

L’int´erˆet des tas pour les tris : Au§3, on a expliqu´e comment obtenir un algorithme de tri en transformant une liste en arbre binaire de recherche. Ici c’est bien plus imm´ediat avec les tas puisque si on sait ranger les donn´ees en un tas, `a chaque fois la premi`ere entr´ee donnera le max.

de la liste.

4.2 Organisation en tas

But de cette partie : prendre une liste quelconque et la r´eorganiser en un tas.

On va donc g´erer les tas `a l’aide de listes pythons : chaque liste python sera interpr´et´ee menta- lement par nous comme associ´ee `a un arbre binaire (qui n’est pas forc´ement un tas). Par exemple pourT=[5,2,6,0,1,9,1,5]

2. En fait, il s’agit detas-max, en rempla¸cant sup´erieur par inf´erieur, on a la notion detas-min.

(6)

Ainsi, on ne manipule que des listes simples, la structure d’arbre n’apparaˆıt pas dans le codage, mais il faut comprendre que pour chaqueio`u cela a un sensT[i]a pour filsT[2i+1]et T[2i+2].

A l’inverse le p`ere deT[i]est T[(i-1)//2].

Par commodit´e, on notera pere(i)pour (i-1)//2,gauche(i)=2*i+1et droite(i)=2i+2.

a) Ecrire une fonctionestUnTasqui re¸coit une listeTet renvoieTrueouFalsessiTrepr´esente un tas.

b) Avec les hypoth`eses 0≤i≤ limiteetlimite≤ longueur(T), ´ecrire un fonctionmaximum(T,i,limite) qui retourne le plus petit entieriMaxv´erifiant toutes les conditions suivantes :

iMax<limiteet iMax∈ {i,gauche(i),droite(i)}

T[iMax] ≥ T[i]

gauche(i)<limite ⇒ T[iMax] ≥ T[gauche(i)]

droite(i)<limite ⇒ T[iMax] ≥ T[droite(i)]

En d’autres termes maximum(T,i,limite)retourne l’indice (inf´erieur `a limite) de la plus grande des trois valeurs T[i], T[gauche(i)], T[droite(i)]. En cas de valeurs ´egales, le plus petit indice est retourn´e.

Par exemple, avec tableau T ci-dessus, max(T,0,8)=2 puisque T[0]=5, T[1]=2, etT[2]=6, donc la valeur maximum est atteinte pour i=2.

c) Soit la fonction r´ecursivePythonsuivante :

def entasserRecursif(T,i,limite):

iMax=maximum(T,i,limite) if iMax!=i:

echange(T,i,iMax)

entasserRecursif(T,iMax,limite)

avec :

def echange(T,i,j):

aux=T[i]

T[i]=T[j]

T[j]=aux

On fait l’appel de entasserRecursif(T,0,8)o`u Test la liste repr´esentant l’arbre suivant :

Dessiner l’arbre repr´esentantTapr`es cet appel deentasserR´ecursif(T,0,8)

d) L’algorithme entasserRecursif(T,i,limite)´echange des valeurs du tableau de haut en bas,en suivant une branche de l’arborescence. Cela a pour effet de fairedescendredes petites valeurs, et de faire monter les grandes valeurs. Il est donc possible de construire un tas, en it´erant cet algorithme sur les indices d´ecroissants du tableau.

Construire ainsi une fonctionconstruireTas(T)qui transforme un tableauTen tas.

e) En d´eduire un algorithme de tri, qui prend une liste et la trie (par ordre d´ecroissant), grˆace

`

a la structure de tas.

Références

Documents relatifs

L’insertion dans un arbre binaire de recherche consiste `a descendre dans l’arbre comme dans un test d’appartenance, jusqu’`a la feuille du dernier appel r´ecursif : on

La profondeur du nœud ou d’une feuille d’un arbre hétérogène est le nombre d’arêtes du plus court chemin reliant ce nœud ou cette feuille à la racineB. On supposera que β ne contient

b) Écrivez un fonction qui calcule la longueur du plus grand &#34;trou&#34; entre deux intervalles (d'un ABRI)..

b) Écrivez un fonction qui calcule la longueur du plus grand &#34;trou&#34; entre deux intervalles (d'un ABRI)..

[r]

il reste deux sous arbres ; on enlève la plus petite étiquette x du sous arbre droit, qu'on place comme nouvelle racine. Il reste à trouver x et à l'enlever ; pour enlever la

Un arbre de d´ ecision repr´ esente les comparaisons (` a l’exclusion de toute autre op´ eration) effectu´ ees par un algorithme de tri lorsqu’il traite une entr´ ee de taille

La longueur d’un chemin de la racine ` a une feuille dans l’arbre de d´ ecision est ´ egale au nombre de comparaisons n´ ecessaires au tri pour parvenir ` a la r´ eponse