Vous êtes sur la page 1sur 30

Cours 2: Arbres

Marie-Pierre Béal

Université Paris-Est Marne-la-Vallée


Plan

1 Exemples

2 Définitions

3 Parcours d’un arbre binaire

4 Compression de texte
Exemples

Structures non-linéaires
Arbres généalogiques
Systèmes de fichiers
Documents structurés
Autres...

XML
Extensible Markup Language, langage de balisage extensible (en
Français), est un langage de balisage générique héritier de SGML. La
syntaxe est dite  extensible  car elle permet de définir des espaces de
noms, c’est-à-dire des dialectes avec chacun leur vocabulaire et leur
grammaire.
Exemple : XHTML, XSLT, RSS, SVG.
Exemples

Structures non-linéaires
Arbres généalogiques
Systèmes de fichiers
Documents structurés
Autres...

XML
Extensible Markup Language, langage de balisage extensible (en
Français), est un langage de balisage générique héritier de SGML. La
syntaxe est dite  extensible  car elle permet de définir des espaces de
noms, c’est-à-dire des dialectes avec chacun leur vocabulaire et leur
grammaire.
Exemple : XHTML, XSLT, RSS, SVG.
33

15 47

10 20 38 51
x

5 18 36 39 49
Définitions

Définition
Un arbre est un ensemble de nœuds éventuellement vide tel que
1) Si l’arbre n’est pas vide il y a un unique nœud appelé racine.
2) Chaque nœud distinct de la racine a un unique nœud père et est fils
de son père. La racine n’a pas de père.

Définition récursive
Un arbre est un ensemble de nœuds éventuellement vide tel que
1) Si l’arbre n’est pas vide il y a un unique nœud appelé racine.
2) Les nœuds distincts de la racine peuvent être groupés en m ≥ 0
ensembles disjoints constituant des arbres non vides. Chacun de ces
ensembles est un sous-arbre de la racine.
Définitions

Définition
Un arbre est un ensemble de nœuds éventuellement vide tel que
1) Si l’arbre n’est pas vide il y a un unique nœud appelé racine.
2) Chaque nœud distinct de la racine a un unique nœud père et est fils
de son père. La racine n’a pas de père.

Définition récursive
Un arbre est un ensemble de nœuds éventuellement vide tel que
1) Si l’arbre n’est pas vide il y a un unique nœud appelé racine.
2) Les nœuds distincts de la racine peuvent être groupés en m ≥ 0
ensembles disjoints constituant des arbres non vides. Chacun de ces
ensembles est un sous-arbre de la racine.
Définitions

Quelques définitions
Nœud interne : c’est un nœud qui possède au moins un fils ;
Feuille : il s’agit d’un nœud qui ne possède fils ;
Ascendant/Descendant : Les ascendants (resp. descendants) est
l’ensemble constitué du père (resp. des fils) d’un nœud ainsi que
leurs ascendants (resp. descendants).
Arbres binaires

Arbre binaire
Un arbre binaire est un arbre tels que tout nœud a au plus un fils
gauche et au plus un fils droit.

33 6= 33

15 47 47 15

10 20 10 20
Définitions

Définitions
Chemin de la racine à un nœud : suite de nœuds passant de père à
fils allant de la racine au nœud.
Profondeur d’un nœud : nombre d’ascendants du noeud
Hauteur d’un arbre : La hauteur de l’arbre vide est 0. La hauteur
d’un arbre non vide est 1 + la plus grande hauteur des sous-arbres
de la racine.
Parcours

Parcours préfixe

Parcours prefixe(Arbre A)
1 if A est non vide
2 then
3 afficher l’étiquette de A
4 Parcours prefixe(fils gauche de A)
5 Parcours prefixe(fils droit de A)
Parcours

Parcours suffixe

Parcours suffixe(Arbre A)
1 if A est non vide
2 then
3 Parcours suffixe(fils gauche de A)
4 Parcours suffixe(fils droit de A)
5 afficher l’étiquette de A
Parcours

Parcours infixe ou interne

Parcours interne(Arbre A)
1 if A est non vide
2 then
3 Parcours interne(fils gauche de A)
4 afficher l’étiquette de A
5 Parcours interne(fils droit de A)
Arbres binaires en C

typedef struct node {


int val;
struct node* left;
struct node* right;
} Node, *Tree;

Tree create_node (int val, Tree left, Tree right) {


Tree a = (Tree) malloc(sizeof(Node));
if (a == NULL) return NULL;
a -> val = val;
a -> left = left;
a -> right = right;
return a;
}
Arbres binaires en C

/* la hauteur est 0 pour l’arbre vide */


int height(Tree a) {
if (a == NULL) return 0;
return 1 + max(height(a -> left), height(a -> right));
}

void prefix(Tree a) {
if (a == NULL) return;
printf("%d ", a -> val);
prefix(a -> left);
prefix(a -> right);
}
Parcours d’arbres planaires en Java
package fr.umlv.tree;
public class Tree {
private Node root;
public Node getRoot(){
return root;
}
public Tree(Node root) {
this.root = root;
}
public boolean isEmpty(){
return root == null;
}
public void prefix(){
if (! isEmpty()) {
root.prefix();
}
}
Parcours d’arbres planaires en Java
public class Node {
private int val;
private List<Node> list;
public Node(int val){
this.val = val;
list = new LinkedList<Node>();
}
public Node(int val, List<Node> list){
this.val = val;
this.list = list;
}
public void prefix(){
System.out.print(val+ " ");
for (Node n : list){
n.prefix();
}}
}
Parcours d’arbres planaires en Java

Un nœud a une liste de nœuds fils


public class Test {
public static void main(String[] args) {
LinkedList<Node> list = new LinkedList<Node>();
list.add(new Node(2));
list.add(new Node(3));
list.add(new Node(4));
Node root = new Node(1, list);
Tree t = new Tree(root);
t.prefix();
}
}
Compression de texte

Codage
lecture du texte source
calcul du nombre d’occurrence de chaque lettre
calcul d’un code
codage du texte à partir du code
obtention du texte compressé
encodage du code
Décodage
lecture du fichier compressé
décodage du code
décodage du texte compressé à partir du code
Code

Définition
Un code est un ensemble de mots non vides tel que tout mot admet au
plus une décomposition en produit (ou concaténation) de mots du code.

Définition
Un code préfixe est un ensemble de mots non vides tel qu’aucun mot
du code n’est préfixe d’un autre mot du code.

Exemples
C1 = {00, 01, 10, 11}
C2 = {0, 10, 11}
Décodage unique et séquentiel de x ∈ C ∗ avec C = 0∗ 1 :
001|1|00001|1|1|0001|
Bijection : code préfixe ↔ arbre binaire

C = {a = 0, b = 10, c = 11}

0 1
a
0 1
b c
Compression statistique
Code du texte en fonction de la fréquence des lettres
t =abr ac ad abr a
a : 5 fois
b : 2 fois
c : 1 fois
d : 1 fois
r : 2 fois

0 1
a
0 1

0 1 0 1
b r c d
Compression statistique

Texte codé
z =01001010110011101001010
23 bits (si on ne compte pas le code) contre 11 × 8 en ASCII
Décodage
0|100|101|0|110|0|111|0|100|101|0|
a b r a c a d a b r a
Arbres pondérés

t texte initial, z texte compressé


p(a) nombre d’occurrences de a dans t
h(a) mot de code associé à a
X
|z| = p(a)h(a)
a∈A

Problème
Connaissant p : A → N \ {0}, calculer h : A → {0, 1}∗ tel que
h(A) est un code préfixe
P
a∈A p(a)h(a) est minimal
Arbres pondérés

t texte initial, z texte compressé


p(a) nombre d’occurrences de a dans t
h(a) mot de code associé à a
X
|z| = p(a)h(a)
a∈A

Problème équivalent
Déterminer un arbre binaire complet t dont les feuilles sont les lettres
de A avec p : Feuilles(t) → N \ {0} tel que
P
Poids(t) = f feuille de A p(f )niveau(f ) est minimal
Arbre pondéré

Arbre de Huffman
Un arbre de Huffman est un arbre binaire complet T dont les feuilles
sont les lettres de A tel que pour p : Feuilles(T ) → N \ {0}
P
Poids(T ) = f feuille de A p(f )niveau(f ) est minimal.

0 1
a
0 1

0 1 0 1
b r c d
Poids(T ) = 5 × 1 + 2 × 3 + 1 × 3 + 1 × 3 = 23 =
longueur du texte compressé
Propriétés

T un arbre pondéré, p :→ N \ {0}, A = Feuilles(T )


T est un arbre de Huffman implique que T est un arbre binaire
complet.
T est un arbre de Huffman et card(A) > 1 implique que, à une
permutation des feuilles près, T possède un sous-arbre (x, f , g ) tel
que f et g sont des feuilles avec p(f ) et p(g ) minimaux.
Soit S obtenu de T en remplaçant (x, f , g ) par la feuille y . Soit
q : Feuilles(S) → N \ {0} définie par
q(y ) = p(f ) + p(g )
q(u) = p(u) pour u 6= y .
Alors T est un arbre de Huffman pour p si et seulement si S est
un arbre de Huffman pour q.
Preuve : Poids(T ) = Poids(S) + p(f ) + p(g ).
Algorithme de Huffman

p : A → N \ {0}
arbre élémentaire : Xa = (xa ) pour chaque lettre a ∈ A

Huffman(Alphabet A, fonction p) : arbre T


1 L ← (Xa | a ∈ A) // L est une liste d’arbres
2 while |L| > 1
3 do
4 b, c ← arbres de L avec p(b), p(c) minimaux
5 y ← (nouveau noeud, b, c)
6 p(y ) ← p(b) + p(c)
7 remplacer b, c par y dans L
8 return l’unique arbre de L // Temps linaire si p est trié
Implémentation

lettre p g d
0 a 5 − −
1 b 2 − −
2 r 2 − −
3 c 2 − −
4 d 1 − −
5 − 2 3 4
6 − 4 1 2
7 − 6 5 6
8 − 11 0 7
Taille de la table : 2 card(A) − 1
Calcul :
tri en temps O(card(A) log(card(A)))
construction de l’arbre en temps O(card(A))