Algorithmique et structures de donnes en C - PowerPoint PPT Presentation

1 / 31
About This Presentation
Title:

Algorithmique et structures de donnes en C

Description:

le TDA ARBRE BINAIRE utilise un TDA ELEMENT incarn par des entiers (ou des caract res) ... aussi un TDA ELEMENT mais incarn par des couples (arbres, position) ... – PowerPoint PPT presentation

Number of Views:204
Avg rating:3.0/5.0
Slides: 32
Provided by: deloz
Category:

less

Transcript and Presenter's Notes

Title: Algorithmique et structures de donnes en C


1
Algorithmique et structures de données en C
Cours 6
Les arbres (3) Parcours
É. Delozanne, L2-S4-prog4, Paris
5 Elisabeth.Delozanne_at_math-info.univ-paris5.fr htt
p//www.math-info.univ-paris5.fr/delozanne/
2
Parcourir un arbre ?
  • parcours
  • examiner les nuds dun arbre pour effectuer un
    traitement
  • 2 types de parcours classiques sur les arbres
    binaires

en profondeur à main gauche (récursif par nature)
en largeur (itératif par nature)
3
Parcours d'arbres binaires récursifs/itératifs
  • Plan du cours
  • parcours en profondeur à main gauche
  • algorithme récursif général
  • cas particuliers (parcours préfixe, infixe,
    postfixe)
  • algorithme itératif général utilise une pile
  • application calcul de la hauteur d'un arbre
  • simplification dans le cas d'un parcours préfixe
  • parcours en largeur (par niveaux, hiérarchique)
  • utilise une file
  • récursivité et itération

4
Objectifs du cours (et TD)
  • Mise en uvre en C dalgorithmes (un peu)
    complexes
  • Culture informatique de base sur les algorithmes
    récursifs et itératifs et sur la compilation
  • Vue abstraite sur les parcours darbres pour
    savoir les écrire plus facilement
  • Compétence à acquérir
  • Savoir écrire rapidement et sans erreur les
    algorithmes récursifs classiques de parcours
    darbres binaires
  • Afficher, lire, construire, hauteur, taille,
    libérer la mémoire, tests etc.
  • Savoir programmer un parcours en largeur

5
Parcours en profondeur à main gauche
  • chemin qui descend toujours le plus à gauche
    possible
  • chaque nud est rencontré 3 fois
  • à la descente avant la visite du sous-arbre
    gauche
  • on applique au nud le traitement 1
  • Après la visite du sous-arbre gauche et avant de
    descendre dans le sous-arbre droit
  • on applique au nud le traitement 2
  • (et dernière fois) quand les deux sous-arbres ont
    été parcourus, en remontant à droite
  • on applique au nud le traitement 3
  • si l'arbre est vide on lui applique un traitement
    appelé terminaison

6
Parcours récursif en profondeur à main gauche
  • Algorithme Parcours (A)
  • si A est vide
  • alors terminaison(A)
  • sinon
  •  traitement1 (A)
  •  Parcours(sous-arbreGauche(A)
  •  traitement2 (A)
  •  Parcours(sous-arbreDroit(A)
  •  traitement3 (A)

Exemple void ArbinTracer(ARBIN A) if
(ArbinVide(A)) / terminaison / printf("()
")  else ElementAfficher(ArbinEtiquette(A)
) / traitement 1 / ArbinTracer(ArbinGauche
(A)) ElementAfficher(ArbinEtiquette(A))
/ traitement 2 / ArbinTracer(ArbinDroit(A)
) ElementAfficher(ArbinEtiquette(A)) /
traitement 3 /
7
Cas particuliers
  • Lorsque le noeud est traité une seule fois
  • Parcours préfixe (Racine Gauche Droit)
  • le nud racine est traité au premier passage
    avant le parcours des sous-arbres
  • Parcours infixe ou symétrique (Gauche Racine
    Droit)
  • le nud racine est traité au second passage
  • après le parcours du sous-arbre gauche
  • et avant le parcours du sous-arbre droit
  • Parcours postfixe (Gauche Droit Racine )
  • le nud racine est traité en dernier après le
    parcours des sous-arbres

8
Parcours préfixe (R G D)
  • le nud racine est traité au premier passage
    avant le parcours des sous-arbres
  • ParcoursPréfixe(A)
  • si A est vide
  • alors terminaison(A)
  • sinon
  • traitement (A)
  • ParcoursPréfixe(sous-arbreGauche de A)
  • ParcoursPréfixe(sous-arbreDroit de A)

9
Exemple RGD
  • Afficher les étiquettes d'un arbre (ordre
    préfixe)
  • terminaison afficher arbre vide () - juste
    pour voir
  • traitement 1 afficher l'étiquette
  • void ArbinAfficherPref(ARBIN A)
  • if (ArbinVide(A))
  • printf("() ")  / terminaison /
  • else
  • ElementAfficher(ArbinEtiquette(A)) /
    traitement 1 /
  • ArbinAfficherPref(ArbinGauche(A))
  • ArbinAfficherPref(ArbinDroit(A))

10
Parcours infixe ou symétrique (G R D)
  • le nud racine est traité au second passage
    après le parcours du sous-arbre gauche et avant
    le parcours du sous-arbre droit
  • ParcoursInfixe(A)
  • si A est vide
  • alors terminaison(A)
  • sinon
  • ParcoursInfixe(sous-arbreGauche de A)
  • traitement (A)
  • ParcoursInfixe(sous-arbreDroit de A)

11
Exemple GRD
  • Afficher les étiquettes d'un arbre (ordre infixe)
  • terminaison afficher arbre vide ()
  • traitement 2 afficher l'étiquette
  • void ArbinAfficherInf(ARBIN A)
  • if (ArbinVide(A))
  • printf("() ")  / terminaison /
  • else
  • ArbinAfficherInf(ArbinGauche(A))
  • ElementAfficher(ArbinEtiquette(A))
  • / traitement 2 /
  • ArbinAfficherInf(ArbinDroit(A))

12
Parcours postfixe (G D R)
  • le nud racine est traité au troisième passage
    après le parcours des sous-arbres gauche et droit
  • ParcoursPostfixe(A)
  • si A est vide
  • alors terminaison(A)
  • sinon
  • ParcoursPostfixe(sous-arbreGauche de A)
  • ParcoursPostfixe(sous-arbreDroit de A)
  • traitement (A)

13
Exemples GDR
  • Afficher les étiquettes d'un arbre (ordre
    postfixe)
  • terminaison afficher arbre vide
  • traitement 3 afficher l'étiquette
  • code C
  • void ArbinAfficherPost(ARBIN A)
  • if (ArbinVide(A))
  • printf("() ")  / terminaison /
  • else
  • ArbinAfficherPost(ArbinGauche(A))
  • ArbinAfficherPost(ArbinDroit(A))
  • ElementAfficher(ArbinEtiquette(A)) /
    traitement 3 /

14
"Dérécursiver"
  • dérécursiver
  • transformer un algorithme récursif en algorithme
    itératif
  • pour des raisons d'efficacité (économie de temps
    et de mémoire)  on  peut être amené à
    "dérécursiver" certains algorithmes
  •  on  le plus souvent les compilateurs
  • méthodes générales pour supprimer
  • un appel récursif terminal
  • utilise une boucle tant que
  • un appel récursif non terminal
  • utilise une pile

15
Parcours itératif en profondeur à main gauche
  • idée une pile mémorisant le nud courant et la
    direction future
  • descente (à gauche du nud, 1ier passage)
  • effectuer le traitement 1 sur la racine
  • empiler le nud et la direction future (descendre
    à dr., 2ième passage)
  • descendre à gauche sur le sous-arbre gauche
  • remontée gauche (2ième passage)
  • effectuer le traitement 2 sur la racine
  • empiler le nud et la direction future (remonter
    à droite, 3ième passage)
  • descendre à gauche sur le sous-arbre droit
  • remontée droite (3ième passage)
  • effectuer le traitement 3 sur la racine
  • dépiler le nud et le sens de la visite sur ce
    nud

16
Parcours itératif en profondeur à main gauche
  • A l'arbre à parcourir
  • créer une pile vide P , direction descente
    gauche fini A non vide
  • tant que (pas fini)
  • Si A est vide
  • alors
  • terminaison
  • Si P est vide alors fini sinon (A et direction)
    dépiler
  • si (pas fini) selon direction
  • direction descente gauche
  • traitement 1, empiler (A, desc. dr),
  • A ss-arbGauche (A) (desc. à g. sur le
    sous-arbre gauche)
  • direction descente droite
  • traitement 2, empiler (A, montée. dr),
  • A ss-arbDroit (A) , direction descente
    gauche(descendre à gauche sur le sous-arbre
    droit)
  • direction montée droite
  • traitement 3,
  • Si P est vide alors fini sinon (A et direction)
    dépiler
  • détruire la pile P

17
Exemple calcul de la hauteur d'un arbre
  • hauteur(A) (algorithme récursif)
  • si A est vide retourner -1
  • sinon
  • hg Hauteur(sous-arbreGauche(A)
  • hd Hauteur(sous-arbreDroit(A)
  • si hg gt hd
  • retourner hg 1
  • sinon retourner hd 1

18
Calcul itératif de la hauteur d'un arbre binaire
  • A arbre à parcourir, h -1, max -1,
  • créer une pile vide P , direction descente
    gauche
  • répéter jusqu'à Pile vide et direction montée
    droite
  • si A est vide alors
  • direction montée droite
  • si h gt max alors max h
  • si (Pile non vide ou direction ? montée droite)
    alors selon direction
  • direction descente gauche
  •   h , empiler (A, desc. dr),
  •  A ss-arbGauche (A)
  • direction descente droite
  •  h, empiler (A, montée. dr),
  •  A ss-arbDroit (A) , direction descente
    gauche
  • direction montée droite
  • h--, dépiler le nud A et la direction
  • détruire P et retourner max

19
Codage en C
  • idée géniale utiliser
  • le TDA PILE (cours 3) et le TDA ARBRE BINAIRE
    (cours 5)
  • problème
  • le TDA ARBRE BINAIRE utilise un TDA ELEMENT
    incarné par des entiers (ou des caractères)
  • le TDA PILE utilise lui aussi un TDA ELEMENT mais
    incarné par des couples (arbres, position)
  • le souk !
  • un même identificateur (ELEMENT) désigne deux
    types différents
  • solution
  • en C bricolo
  • en C les template (polymorphisme
    paramétrique)
  • en Smalltalk, Java polymorphisme dhéritage

20
Simplifications de l'algorithme général
  • exemple Parcours préfixe itératif (à la
    Sedgewick
  • A arbre à parcourir
  • créer une Pile vide P
  • si l'arbre A est non vide empiler A
  • tant que P est non vide répéter
  • dépiler dans A
  • traiter (A)
  • si le sous-arbre droit est non vide, l'empiler
  • si le sous-arbre gauche est non vide, l'empiler
  • détruire (P)

21
Parcours d'arbres binaires récursifs/itératifs
  • Plan du cours
  • parcours en profondeur à main gauche
  • algorithme récursif général
  • cas particuliers (parcours préfixe, infixe,
    postfixe)
  • algorithme itératif général utilise une pile
  • application calcul de la hauteur d'un arbre
  • simplification dans le cas d'un parcours préfixe
  • parcours en largeur (par niveaux, hiérarchique)
  • utilise une file
  • récursivité et itération

22
Parcours en largeur (hiérarchique, par niveau)
  • stratégie pas du tout récursive
  • traitement des nuds par niveau traiter les
    frères avant les fils
  • dans la représentation graphique
  • 1. de gauche à droite
  • 2. de haut vers le bas
  • utilisation d'une file
  • on traite un nud
  • on fait entrer dans la file
  • dabord son fils gauche
  • puis son fils droit

23
Algorithme
  • ParcoursEnLargeur (A)
  • créer une file vide F
  • si A est non vide alors
  • entrer A dans F
  • tant que F non vide
  • A sortir(F)
  • traiter (A)
  • si ss-arbGauche(A) non vide l'entrer dans F
  • si ss-arbDroit(A) non vide l'entrer dans F
  • FinSi
  • détruire F

24
Affichage en largeur
  • void ArbinAfficherLargeur(ARBIN A)
  • FFILE F FileCreer(20) ELTSPCL elt
  • if ( ! ArbinVide(A) )
  • elt EltSpclInit(A,1) FileEntrer(elt, F)
  • while ( ! FileVide (F) )
  • A EltSpclArbre(FileSortir(F))
  • ElementAfficher(ArbinEtiquette(A))
  • if( ! ArbinVide(ArbinGauche(A)) )
  • elt EltSpclInit(ArbinGauche(A),1)
    FileEntrer(elt, F)
  • if( ! ArbinVide(ArbinDroit(A)) )
  • elt EltSpclInit(ArbinDroit(A),1)FileEntrer(e
    lt, F)
  • FileDetruire(F)

25
Parcours d'arbres binaires récursifs/itératifs
  • Plan du cours
  • parcours en profondeur à main gauche
  • algorithme récursif général
  • cas particuliers (parcours préfixe, infixe,
    postfixe)
  • algorithme itératif général utilise une pile
  • application calcul de la hauteur d'un arbre
  • simplification dans le cas d'un parcours préfixe
  • parcours en largeur (par niveaux, hiérarchique)
  • utilise une file
  • récursivité et itération

26
Y'avait longtemps...
  • factorielle version récursive
  • long factorielle (int n)
  • if (n lt 0) return 1
  • else return n factorielle (n - 1)
  • factorielle version itérative
  • long factorielle (int n)
  • int r 1
  • while ( n gt 1) r r n n --
  • return r

27
Et sa copine ...fibonacci
  • fibonacci version récursive
  • long fibonacci (int n)
  • if (n lt 1) return 1
  • else return fibonacci (n - 1) fibonacci (n -
    2)
  • fibonacci version itérative
  • long fibonacci (int n)
  • int u, v u v 1
  • for (i 3 i lt n i) u u v v
    u - v
  • return u

28
Récursif versus itératif
  • sur ces 2 exemples triviaux la solution itérative
    est meilleure
  • certains compilateurs astucieux remplacent
  • l'appel récursif terminal par une boucle tant que
  • un appel non terminal par un algorithme itératif
    utilisant une pile
  • certains algorithmes sont  naturellement
    récursifs
  • 1) algorithmes récursifs de type diviser pour
    résoudre
  • 2 appels récursifs traitant chacun en gros la
    moitié des données sans calcul redondant
  • 2) algorithmes récursifs de type combiner pour
    résoudre
  • commencer par résoudre des cas triviaux
  • puis en les combinant résoudre des cas complexes

29
Bilan
  • un algorithme récursif peut être transformé en
    algorithme itératif (ne le faire que si on voit
    que l'algorithme "patine" ou besoin impérieux)
  • un programme itératif n'est pas toujours plus
    efficace qu'un programme récursif
  • la récursivité est centrale
  • en informatique dite théorique pour distinguer
    les problèmes (problèmes calculables) qu'une
    machine peut résoudre en temps fini
  • en IA et en recherche opérationnelle pour
    résoudre des problèmes complexes
  • en programmation pour traiter de manière simple
    de nombreux problèmes sur les arbres binaires
    (recherche, tri etc.)

30
Retenir
  • Un algorithme itératif nest pas forcément plus
    rapide quun algorithme itératif
  • Certains algorithmes sont mieux traités par des
    algorithmes itératifs
  • Dautres sont mieux traités par des algorithmes
    récursifs

31
Auto-évaluation cours 6
  • Quest-ce que parcourir un arbre ?
  • Quels sont les parcours classiques sur les arbres
    ?
  • Les algorithmes itératifs sont-ils toujours plus
    efficaces que les algorithmes récursifs ?
    Réciproque ?
  • Donner des exemples de parcours en profondeur à
    main gauche ?
  • Même question pour le parcours hiérarchique
  • Écrire en C les parcours classiques sur les
    arbres binaires étudiés en cours, en TD
Write a Comment
User Comments (0)
About PowerShow.com