Académique Documents
Professionnel Documents
Culture Documents
- p. 1/56
Les arbres
Les arbres
● Arbres
■ Un arbre est défini de manière récursive, c’est:
● Arbres binaires ◆ Soit un arbre atomique (ou noeud terminal ou feuille)
● ABR
● Tas ◆ Soit un noeud ayant pour fils d’autre arbres.
● AST
● Hash code ■ En général on étiquete les noeuds avec une valeur.
Introduction
N1
Pointeur de fonctions
Erreurs courante en C
■ Le noeud N1 est la racine de l’arbre.
N6
■ Les noeuds N3, N4, N5 et N8 sont N2
- p. 2/56
Parcours d’un arbre binaire
Les arbres
● Arbres
■ Un arbre binaire est un arbre dont les noeuds ont au plus
● Arbres binaires
● ABR
deux fils
● Tas
● AST
■ Les algorithmes travaillant sur des arbres sont généralement
● Hash code récursifs.
Introduction
■ En langage de description algorithmique, on suppose
Pointeur de fonctions
disposer de fonctions d’accès: à partir de chaque noeud N
Erreurs courante en C
on peut atteindre son père pere(N) et ses fils filsDroit(N),
filsGauche(N)
PRODECURE parcours(ARBRE N)
SI filsGauche(N)6= NULL ALORS parcours(filsGauche(N)) FINSI
traiter(N);
SI filsDroit(N)6= NULL ALORS parcours(filsDroit(N)) FINSI
FIN
- p. 3/56
Les arbres
● Arbres *
● Arbres binaires
● ABR
● Tas
● AST + +
● Hash code
Introduction
Pointeur de fonctions
5 * * *
Erreurs courante en C
2 3 10 10 9 9
- p. 4/56
Affichage d’une expression arithmétique
Les arbres
*
● Arbres
● Arbres binaires
● ABR
+ +
● Tas
● AST
● Hash code
5 * * *
Introduction
Pointeur de fonctions 2 3 10 10 9 9
Erreurs courante en C
PRODECURE parcours(ARBRE N)
SI (valeur(N)==’+’) ALORS print(’(’) FINSI
SI filsGauche(N)6= NULL ALORS parcours(filsGauche(N)) FINSI
PRINT(valeur(N));
SI filsDroit(N)6= NULL ALORS parcours(filsDroit(N)) FINSI
SI (valeur(N)==’+’) ALORS print(’)’) FINSI
FIN
■ En rajoutant des parenthèses autour d’une addition:
■ (5 + 2 ∗ 3) ∗ (10 ∗ 10 + 9 ∗ 9)
- p. 5/56
Les arbres
● Arbres
■ Suivant l’ordre dans lequel on écrit les instructions de la
● Arbres binaires
● ABR
fonction de parcours, l’ordre de parcours des noeuds est
● Tas différent.
● AST
● Hash code ■ Trois possibilités principales:
Introduction ◆ Parcours préfixe : racine, sous-arbre gauche, sous-arbre
Pointeur de fonctions droit
Erreurs courante en C ◆ Parcours infixe : sous-arbre gauche, racine, sous-arbre
droit
◆ Parcours postfixe : sous-arbre gauche, sous-arbre droit,
racine
■ Il existe d’autres types de parcours moins facile a réaliser:
◆ parcours en largeur d’abord.
- p. 6/56
Parcours préfixe
Les arbres
1
● Arbres *
● Arbres binaires
● ABR
● Tas
2 + 7 +
● AST
● Hash code
Introduction
3 4
5 * 8 * 11 *
Pointeur de fonctions
Erreurs courante en C
5 2 6 3 9 10 10 10 12 9 13 9
PRODECURE parcoursPrefixe(ARBRE N)
traiter(N);
SI filsGauche(N)6= NULL ALORS parcours(filsGauche(N)) FINSI
SI filsDroit(N)6= NULL ALORS parcours(filsDroit(N)) FINSI
FIN
* ( + 5 * 2 3 ) (+ * 10 10 * 9 9)
- p. 7/56
Parcours infixe
Les arbres 6
● Arbres *
● Arbres binaires
● ABR
● Tas
2 + 10 +
● AST
● Hash code
Introduction
1 4 8 12
Pointeur de fonctions
5 * * *
Erreurs courante en C
3 5 7 9 11 13
2 3 10 10 9 9
PRODECURE parcoursInfixe(ARBRE N)
SI filsGauche(N)6= NULL ALORS parcours(filsGauche(N)) FINSI
traiter(N);
SI filsDroit(N)6= NULL ALORS parcours(filsDroit(N)) FINSI
FIN
( 5 + 2 * 3 ) * ( 10 * 10 + 9 * 9 )
- p. 8/56
Parcours postfixe
Les arbres 13
● Arbres *
● Arbres binaires
● ABR
● Tas
● AST 5 + 12 +
● Hash code
Introduction
1 4 8 11
Pointeur de fonctions
5 * * *
Erreurs courante en C
2 3 3 6 9 10
2 10 7 10 9 9
PRODECURE parcoursPostfixe(ARBRE N)
SI filsGauche(N)6= NULL ALORS parcours(filsGauche(N)) FINSI
SI filsDroit(N)6= NULL ALORS parcours(filsDroit(N)) FINSI
traiter(N);
FIN
( 5 2 3 * + ) (10 10 * 9 9 * +) *
- p. 9/56
Implémentation en C
Les arbres
● Arbres
■ Pour un arbre binaire:
● Arbres binaires struct model_noeud
● ABR
● Tas {
● AST
● Hash code int val;
Introduction struct model_noeud *filsGauche;
Pointeur de fonctions struct model_noeud *filsDroit;
Erreurs courante en C } ;
- p. 10/56
Implémentation en C
Les arbres
● Arbres
■ Pour un arbre N-aire (N≤10):
● Arbres binaires
● ABR
#define N 10
● Tas
● AST
● Hash code struct model_noeud
Introduction {
Pointeur de fonctions int val;
Erreurs courante en C struct model_noeud *enfants[N];
} ;
- p. 11/56
Les arbres
● Arbres
ARBRE nouvelArbre(int val, ARBRE fg, ARBRE fd)
● Arbres binaires {
● ABR
ARBRE temp;
● Tas
● AST
● Hash code
temp= (ARBRE)malloc(sizeof(NOEUD));
Introduction temp->val=val;
Pointeur de fonctions
temp->filsGauche=fg;
temp->filsDroit=fd;
Erreurs courante en C
return(temp);
}
int main()
{
ARBRE arbre,temp1,temp2;
temp1=nouvelArbre(10,NULL,NULL);
temp2=nouvelArbre(20,NULL,NULL);
arbre=nouvelArbre(30,temp1,temp2);
fprintf(stdout,"filsdroit->val=%d\n",arbre->filsDroit->val);
}
- p. 12/56
Cas particulier des arbres binaires
Les arbres
● Arbres *
● Arbres binaires
● ABR
● Tas
● AST + +
● Hash code
Introduction
Pointeur de fonctions
5 * * *
Erreurs courante en C
2 3 10 10 9 9
- p. 13/56
Les arbres
1
● Arbres *
● Arbres binaires
● ABR
● Tas
2 + 3 +
● AST
● Hash code
Introduction
4 5 6 7
Pointeur de fonctions
5 * * *
Erreurs courante en C
8 10 11 10 12 9 13
2 9 3 10 9
Les arbres
1
● Arbres *
● Arbres binaires
● ABR
● Tas
2 + 3 +
● AST
● Hash code
Introduction
4 5 6 7
Pointeur de fonctions
5 * * *
Erreurs courante en C
8 10 11 10 12 9 13
2 9 3 10 9
index 0 1 2 3 4 5 6 7 8 9 10 11 12 13
valeur * + + 5 * * * X X 2 3 10 10 9
i=1
2i + 1 = 3 2i + 2 = 4
- p. 15/56
Exemple
Les arbres
1
● Arbres *
● Arbres binaires
● ABR
● Tas
2 + 3 +
● AST
● Hash code
Introduction
4 5 6 7
Pointeur de fonctions
5 * * *
Erreurs courante en C
8 10 11 10 12 9 13
2 9 3 10 9
index 0 1 2 3 4 5 6 7 8 9 10 11 12 1
valeur * + + 5 * * * X X 2 3 10 10
i=5
2i + 1 = 10 2i + 2 = 10
- p. 16/56
Arbres binaires de recherche
Les arbres
● Arbres
■ Ce sont des arbres binaires de valeurs ordonnées avec les
● Arbres binaires
● ABR
propriétés:
● Tas ◆ Tous les noeuds du sous arbre gauche d’un noeud ont
● AST
● Hash code une valeur inférieure (ou égale) à la sienne
Introduction ◆ Tous les noeuds du sous arbre droit d’un noeud ont une
Pointeur de fonctions valeur supérieure (ou égale) à la sienne
Erreurs courante en C ■ Utilisé pour stocker et rechercher rapidement des éléments
dans une table qui évolue rapidement.
20
3 25
3 12 21 26
8 13
8 6
- p. 17/56
Insertion en ABR
PRODECURE insertionABR(ELEMENT v, ARBRE A)
SI (A==NULL) ALORS
Les arbres
● Arbres
A=nouvelArbre(v,NULL,NULL)
● Arbres binaires SINON
● ABR
● Tas SI (v<valeur(A)) ALORS
● AST
● Hash code insertionABR(filsGauche(A))
Introduction SINON
Pointeur de fonctions insertionABR(filsDroit(A))
Erreurs courante en C FINSI
FINSI
FIN
20 20
3 25 3 25
3 12 21 26 3 12 21 26
8 13 8 13
8 8 6 9
6
- p. 18/56
Arbre équilibré
Les arbres
● Arbres
■ Un arbre binaire est équilibré (AVL pour Adel’son, Vel’Skii et
● Arbres binaires
● ABR
Landis) si pour tout noeud, la différence de profondeur entre
● Tas l’arbre de son fils gauche et l’arbre de son fils droit est au
● AST
● Hash code plus 1 (i.e. 0 ou 1).
Introduction ■ On peut montrer que la hauteur d’un AVL de N noeuds est
Pointeur de fonctions de l’ordre de Log(N )
Erreurs courante en C
■ On peut aussi modifier la procédure d’insertion dans un
arbre de recherche pour que l’arbre résultant soit toujours
équilibré.
■ Pour cela on utilise la transformation de rotation
B A
A B
c a
a b b c
- p. 19/56
File de priorité
Les arbres
● Arbres
■ Une file de priorité est une liste dans laquelle on peut ajouter
● Arbres binaires
● ABR
ou supprimer des éléments, chaque élément ayant une
● Tas priorité. Lors d’une suppression on prend toujours l’élément
● AST
● Hash code de priorité maximum.
Introduction ■ Comment implémenter une file de priorité pour que les
Pointeur de fonctions opérations d’insertion et de suppression aient une
Erreurs courante en C complexité de O(1)
■ On va utiliser une structure de tas.
- p. 20/56
Tas
Les arbres
● Arbres
■ Un tas est un arbre binaire avec les propriétés suivante:
● Arbres binaires ◆ La valeur de chaque noeud est supérieure ou égales à
● ABR
● Tas celle de ces fils.
● AST
● Hash code ◆ L’arbre est quasi complet: tous les étages sont complet
Introduction sauf éventuellement l’étage des feuilles et toutes les
Pointeur de fonctions feuilles de l’étage des feuilles sont regroupées à gauche.
Erreurs courante en C 16
14 10
8 10 9 3
2 4 7
index 0 1 2 3 4 5 6 7 8 9 10 11 12 13
valeur 16 14 10 8 10 9 3 2 4 7 X X X X
- p. 21/56
Les arbres
● Arbres
■ On sait quelle noeud doit être ajouté: c’est le premier noeud
● Arbres binaires
● ABR
libre de l’étage des feuilles, c.a.d La première case libre du
● Tas tableau.
● AST
● Hash code ■ Mais la valeur de ce nouveau noeud est peut être supérieure
Introduction
à son père. Dans ce cas on fait remonter le noeud en
Pointeur de fonctions l’échangeant avec son père.
Erreurs courante en C 16 16
14 10 14 10
8 10 9 3 8 15 9 3
2 4 7 15 2 4 7 10
16
15 10
8 14 9 3
2 4 7 10 - p. 22/56
Suppression dans un tas
Les arbres
● Arbres
■ L’élément à supprimer est toujours la racine (il reste deux
● Arbres binaires
● ABR
arbres)
● Tas
● AST
■ On place le dernier élément de la ligne des feuille en racine
● Hash code
et on le redescend jusqu’à sa place:
Introduction
16 10
Pointeur de fonctions
Erreurs courante en C
15 10 15 10
8 14 9 3 8 14 9 3
2 4 7 10 2 4 7
15 15
10 10 14 10
8 14 9 3 8 10 9 3
2 4 7 2 4 7
- p. 23/56
Complexité
Les arbres
● Arbres
■ Les opérations d’insertion et de retrait et de recherche dans
● Arbres binaires
● ABR
un tas de taille N se font en temps Log(N )
● Tas
● AST
■ On peut utiliser ces propriétés pour construire un algorithme
● Hash code
de tri qui est toujours en N Log(N )
Introduction
■ On insère les éléments dans un tas, puis on les retire un à
Pointeur de fonctions
un.
Erreurs courante en C
■ En pratique, cette technique est moins bonne que QuickSort:
les constantes sont trop grandes.
PRODECURE insertionTas(ELEMENT v, TAS A)
pos=premiereCaseLibre(A)
TANTQUE (A[pos div 2]≤ v) et pos > 0)
A[pos]=A[pos div 2]
pos=pos div 2
FINTANTQUE
A[pos]=v
FIN
- p. 24/56
Arbre de syntaxe abstrait
Les arbres
● Arbres
■ Lorsque l’on veut stocker une expression arithmétique, on a
● Arbres binaires
● ABR
deux types de noeuds: entiers et opérateurs.
● Tas (5 + 2 ∗ 3) ∗ (10 ∗ 10 + 9 ∗ 9)
● AST
● Hash code ■ Quelle structure de donnée utiliser pour stocker une telle
Introduction
expression?
Pointeur de fonctions
■ Une solution souvent utilisée est une hiérarchie de structure
Erreurs courante en C
combinée avec des unions
- p. 25/56
Les arbres
● Arbres
■ Énumération: Permet de définir des constantes:
● Arbres binaires
● ABR
enum {LUNDI, MARDI, MERCREDI}
● Tas
● AST
Définit trois constantes entières avec les valeur LUNDI=0,
● Hash code MARDI=1 et MERCREDI=2. On peut forcer leurs valeur:
Introduction enum {LUNDI=12, MARDI=13, MERCREDI=14 }
Pointeur de fonctions
■ Utilisé pour manipuler des informations symboliques.
Erreurs courante en C
- p. 26/56
Retour sur les constructeurs de type
Les arbres
● Arbres
■ Union: permet de manipuler des variables pouvant prendre
● Arbres binaires
● ABR
deux types différents: par exemple, soit un entier, soit une
● Tas chaîne de caractère. La définition est similaire à celle d’une
● AST
● Hash code structure (info est l’étiquette de l’union):
Introduction union info
Pointeur de fonctions {
Erreurs courante en C int val;
char *oper;
};
union info n;
■ L’utilisation se fait comme pour une structure (struct) sauf
qu’une variable n ne possède que l’un des deux champs:
val ou oper:
n.val=1 ou n.oper=(char *)malloc(2*sizeof(char));
strcpy(oper,"-");
- p. 27/56
Les arbres
● Arbres typedef enum
● Arbres binaires
● ABR
{VALEUR, MULT, ADD, DIV, SUB} typeNoeud;
● Tas
● AST
● Hash code struct model_noeud
Introduction {
Pointeur de fonctions typeNoeud type;
Erreurs courante en C struct model_noeud *filsGauche ;
struct model_noeud *filsDroit ;
union
{
int val;
char *oper;
} info;
};
Les arbres
● Arbres
Le champ type aide a determiner si la valeur est entière ou
● Arbres binaires
● ABR
chaîne de caractère.
● Tas ARBRE nouvelFeuille(int val)
● AST
● Hash code {
Introduction ARBRE temp;
Pointeur de fonctions
- p. 29/56
Les arbres
● Arbres
int afficherArbre(ARBRE arbre)
● Arbres binaires {
● ABR
if ((arbre->type==ADD)||(arbre->type==SUB))
● Tas
● AST fprintf(stdout,"(");
● Hash code
switch (arbre->type)
Introduction {
Pointeur de fonctions
case VALEUR: fprintf(stdout,"%d",arbre->info.val);
break;
Erreurs courante en C
default:
afficherArbre(arbre->filsGauche);
fprintf(stdout,"%s",arbre->info.oper);
afficherArbre(arbre->filsDroit);
};
if ((arbre->type==ADD)||(arbre->type==SUB))
fprintf(stdout,")");
}
- p. 31/56
Exemple d’utilisation
Les arbres
● Arbres
int main()
● Arbres binaires {
● ABR
● Tas
● AST ARBRE arbre, temp1,temp2,temp3;
● Hash code
Introduction
Pointeur de fonctions
temp1=nouvelFeuille(10);
temp2=nouvelFeuille(20);
Erreurs courante en C
temp3=nouvelFeuille(400);
arbre=nouvelOper(ADD,temp1,temp2);
arbre=nouvelOper(MULT,arbre,temp3);
afficherArbre(arbre);
fprintf(stdout,"\n");
return(0);
}
■ resultat:
(10+20)*400
- p. 32/56
Tables de hachage
Les arbres
● Arbres
■Beaucoup d’applications utilisent des dictionnaires:
● Arbres binaires
● ABR
collection dynamique d’objets accédés fréquemment.
● Tas
■ On utilise un attribut de l’objet comme clé pour retrouver
● AST
● Hash code l’objet dans la table stockant les objets.
Introduction
■ Exemple: carnet d’adresse indexé par le nom des
Pointeur de fonctions
personnes.
Erreurs courante en C
■ On ne peut pas trier la table car elle est dynamique.
- p. 33/56
Tables de hachage
Les arbres
● Arbres
■ La table de hachage utilise une fonction de hachage h pour
● Arbres binaires
● ABR
indexer la table contenant l’information: les informations
● Tas concernant "dupont" sont rangées à la case h(”dupont”)
● AST
● Hash code ■ La fonction de hachage est censée disperser les noms
Introduction
inégalement répartis (exemple: beaucoup de noms
Pointeur de fonctions commençant par "du").
Erreurs courante en C
■ Exemple de fonction pour des clés étant des chaînes de
P
caractères: h(x) = ( li=1 x[i]l−1 )modN
ou x[i] est le code ascii de la ieme lettre du nom.
■ Cette fonction donne au plus N index différents (compris
entre 0 et N ), elle est donc utilisé pour une table de taille N
■ Si deux noms ont le même index dans la table
(h(”dupont”) = h(”durand”)) on dit qu’il y a collision.
■ On résout les collisions en utilisant les cases vides de la
table.
- p. 34/56
Exemple de table de hachage
Les arbres
● Arbres
■ Hachage par collision séparées: une table pour indiquer
● Arbres binaires
● ABR
quelle est l’autre case prise en cas de collision.
● Tas paul i nom(i) tel(i) col(i)
● AST
● Hash code 0 pierre 2805 −1
Introduction
roger 1 −1
Pointeur de fonctions
2 −1
Erreurs courante en C
4 −1
5 roger 4501 12
7 −1
pierre
8 −1
9 −1
yves 10 anne 2702 −1
collisions
11 yves 2806 −1
13
Les arbres
● Arbres
■ Hachage par adressage ouvert: on résout les collisions en
● Arbres binaires
● ABR
utilisant les cases suivantes du tableau.
paul i nom(i) tel(i)
● Tas
● AST
● Hash code 0 pierre 2805
Introduction 1
roger
Pointeur de fonctions
2
Erreurs courante en C
5 roger 4501
7 anne 2702
pierre
8 yves 2806
9 laurent 8064
yves 10
11
laurent 12
- p. 36/56
Intérêt des tables de hachage
Les arbres
● Arbres
■ L’intérêt est de s’approcher d’une structure à accès direct
● Arbres binaires
● ABR
(temps constant pour accéder à un élément à partir de sa
● Tas clé).
● AST
● Hash code ■ Si la fonction de hachage est parfaite (pas de collision), c’est
Introduction
gagné.
Pointeur de fonctions
■ En général elle n’est pas parfaite, de nombreuses
Erreurs courante en C
recherches ont sélectionnées des tables de hachage très
performantes pour divers types de données.
■ On a aussi montré que l’on pouvait augmenter ou diminuer
dynamiquement la taille de la table et donc avoir une
fonction de hachage qui est adapté au nombre de donnée
que l’on traite.
- p. 37/56
Les arbres
● Arbres
■ En ce qui concerne le hachage par adressage ouvert, on
● Arbres binaires
● ABR
peut montre que si α est le taux d’occupation de la table
● Tas (α = nbelt /tailletable ), le nombre d’opération en moyenne
● AST
● Hash code pour rechercher un élément est:
◆ 1 + 1
Introduction
2 2(1−α) pour une recherche avec succès
Pointeur de fonctions ◆ 1 + 1
pour une recherche avec échec
2 2(1−α)2
Erreurs courante en C
■ Pour α = 2/3 on fait 2 et 5 opérations. Pour α = 9/10 on fait
5 et 50 opérations.
■ Si on est prêt à a voir une table un peu plus grosse que
nécessaire on a des temps d’accès très bons.
- p. 38/56
Plan
- p. 39/56
- p. 40/56
Un premier exemple
Les arbres
#include <stdio.h>
Introduction
#include <stdlib.h>
Pointeur de fonctions
//declaration de fonction
Erreurs courante en C
int fonct1(int a)
{
fprintf(stdout,"Je suis fonct1(%d)\n",a);
return(0);
}
int main()
{// declaration de pointeur de fonction
int (*foncPtr)(int a);
foncPtr=&fonct1;
(*foncPtr)(10);
return(0);
} - p. 41/56
- p. 42/56
Déclaration d’un pointeur de fonction
- p. 43/56
foncPtr=fonct1;
foncPtr(10);
- p. 44/56
On peut donc ecrire:
Les arbres
#include <stdio.h>
Introduction
#include <stdlib.h>
Pointeur de fonctions
//declaration de fonction
Erreurs courante en C
int fonct1(int a)
{
fprintf(stdout,"Je suis fonct1(%d)\n",a);
return(0);
}
int main()
{// declaration de pointeur de fonction
int (*foncPtr)(int a);
foncPtr=fonct1;
foncPtr(10);
return(0);
} - p. 45/56
Un autre exemple
Les arbres
int main(void)
Introduction
{
Pointeur de fonctions
//comparaison de deux entiers int i,t[6]={1,5,2,3,6,4};
Erreurs courante en C
- p. 46/56
... la fonction tri
Les arbres
void trie(int tableau[], int taille, int (fcomp)(int, int))
Introduction
{
Pointeur de fonctions
int i,j,min;
Erreurs courante en C
//tri par permuation avec fcomp comme fonction de comparaiso
for (i=0;i<taille;i++)
{
min=tableau[i];
for (j=i+1;j<taille;j++)
if (fcomp(tableau[i],tableau[j]))
{
min = tableau[j];
tableau[j]=tableau[i];
tableau[i]=min;
}
}
return ;
} - p. 47/56
- p. 48/56
Passage de fonction par référence
changeOrdre(int (**fcomp1)(int, int), int (*fcomp2)(int, int))
{
Les arbres
*fcomp1=fcomp2;
Introduction
}
Pointeur de fonctions
int main(void)
Erreurs courante en C
{
int i,t[6]={1,5,2,3,6,4};
int (*fcomp)(int,int);
fcomp=croissant;
trie(t, 6, fcomp);
for(i=0;i<6;i++)
fprintf(stdout," %d ",t[i]);
fprintf(stdout,"\n");
changeOrdre(&fcomp,decroissant);
trie(t, 6, fcomp);
for(i=0;i<6;i++) - p. 49/56
fprintf(stdout," %d ",t[i]);
Les arbres
Introduction
Pointeur de fonctions
Erreurs courante en C
- p. 50/56
Confusion entre == et =
Les arbres
■ À ne pas faire:
Introduction
if (size = 0) ....
Pointeur de fonctions
■ Détection: l’option -Wall du compilateur avertit le
Erreurs courante en C
programmeur (warning)
- p. 51/56
- p. 52/56
Problèmes de macros
- p. 53/56
- p. 55/56
Erreurs courante en C
■ exemple de fichier configuration vi:
syntax on " coloration syntaxique
set autoindent " identation
set cindent " pour C
set nopaste
set ts=4 " tabulation a 4 caracteres
set sw=4
■ Sous vi:
◆ == pour indenter la ligne courante,
◆ =G pour identer tout le fichier:
- p. 56/56