Cours 3 : Arbres suite

Documents pareils
Les arbres binaires de recherche

Les structures de données. Rajae El Ouazzani

Java Licence Professionnelle CISII,

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Package Java.util Classe générique

Programme Compte bancaire (code)

Corrigé des exercices sur les références

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Objets et Programmation. origine des langages orientés-objet

ARBRES BINAIRES DE RECHERCHE

Arbres binaires de recherche

Projet de programmation (IK3) : TP n 1 Correction

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

SUPPORT DE COURS. Dr. Omari Mohammed Maître de Conférences Classe A Université d Adrar Courriel : omarinmt@gmail.com

Algorithmique, Structures de données et langage C

ACTIVITÉ DE PROGRAMMATION

Chapitre 10. Les interfaces Comparable et Comparator 1

Utilisation d objets : String et ArrayList

Programmer en JAVA. par Tama

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Plan du cours. Historique du langage Nouveautés de Java 7

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

TD3: tableaux avancées, première classe et chaînes

Threads. Threads. USTL routier 1

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Corrigés des premiers exercices sur les classes

Recherche dans un tableau

Conventions d écriture et outils de mise au point

Algorithmique I. Algorithmique I p.1/??

Quelques Algorithmes simples

Cours d initiation à la programmation en C++ Johann Cuenin

Cours de Programmation Impérative: Zones de mémoires et pointeurs

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

Projet d informatique M1BI : Compression et décompression de texte. 1 Généralités sur la compression/décompression de texte

INF601 : Algorithme et Structure de données

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

Cours de C++ François Laroussinie. 2 novembre Dept. d Informatique, ENS de Cachan

SNT4U16 - Initiation à la programmation TD - Dynamique de POP III - Fichiers sources

Claude Delannoy. 3 e édition C++

Un ordonnanceur stupide

Introduction à la programmation concurrente

Programmation avec des objets : Cours 7. Menu du jour

Chapitre 7. Récurrences

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Résolution de systèmes linéaires par des méthodes directes

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Bases de programmation. Cours 5. Structurer les données

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

as Architecture des Systèmes d Information

Compression de Données - Algorithme de Huffman Document de Conception

Développement mobile MIDP 2.0 Mobile 3D Graphics API (M3G) JSR 184. Frédéric BERTIN

Tp 1 correction. Structures de données (IF2)

Derrière toi Une machine virtuelle!

Les processus légers : threads. Système L3, /31

Problèmes liés à la concurrence

introduction Chapitre 5 Récursivité Exemples mathématiques Fonction factorielle ø est un arbre (vide) Images récursives

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Auto-évaluation Programmation en Java

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Génie Logiciel avec Ada. 4 février 2013

Flux de données Lecture/Ecriture Fichiers

Examen Médian - 1 heure 30

Partie I : Créer la base de données. Année universitaire 2008/2009 Master 1 SIIO Projet Introduction au Décisionnel, Oracle

JAVA TD0. Prise en main du langage Environnement de base JAVA 1

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Principes des langages de programmation INF 321. Eric Goubault

Solutions du chapitre 4

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

TP1 : Initiation à Java et Eclipse

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Ensimag 1ère année Algorithmique 1 Examen 2ième session 24 juin Algorithmique 1

Java 1.5 : principales nouveautés

Une introduction à Java

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Exclusion Mutuelle. Arnaud Labourel Courriel : arnaud.labourel@lif.univ-mrs.fr. Université de Provence. 9 février 2011

Java Licence Professionnelle CISII,

Université Kasdi Merbeh Ouargla FSSI/ Département des maths et de l informatique Corrigé type TD N 8 de ASD2 (Les Graphes)

Licence Sciences et Technologies Examen janvier 2010

Initiation à la programmation en Python

ARDUINO DOSSIER RESSOURCE POUR LA CLASSE

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Le prototype de la fonction main()

Machines virtuelles fonctionnelles (suite) Compilation ML Java

Chapitre 1 : La gestion dynamique de la mémoire

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

TD2 Programmation concurrentielle

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

TD2/TME2 : Ordonnanceur et Threads (POSIX et fair)

Composants Logiciels. Le modèle de composant de CORBA. Plan

#include <stdio.h> #include <stdlib.h> struct cell { int clef; struct cell *suiv; };

Assurance Qualité. Cours de génie logiciel. Renaud Marlet. LaBRI / INRIA (d'après A.-M. Hugues) màj 23/04/2007

Latitude N Longitude E Altitude 376 m RÉSUMÉ MENSUEL DU TEMPS DE JANVIER 2014

Algorithmique et programmation : les bases (VBA) Corrigé


Développement Logiciel

INF 321 : mémento de la syntaxe de Java

Transcription:

Cours 3 : Arbres suite Marie-Pierre Béal Université Paris-Est Marne-la-Vallée

Plan 1 Arbres binaires de recherche Definition Exemple Recherche d un élément Ajout d un élément Retrait d un élément 2 Tas ou File de priorité Definition Exemple Ajout d un élément Retrait du minimum Tri par tas Création d un tas 3 Arbres AVL

Définition Définition Un arbre binaire est un arbre binaire de recherche si pour tout nœud, l étiquette du nœud est supérieure ou égale aux étiquettes des nœuds du sous-arbre gauche et est inférieure ou égale aux étiquettes des nœuds du sous-arbre droit.

Exemple 33 15 47 10 20 Les étiquettes des nœuds sont croisssantes dans l ordre infixe. Exercice : écrire un code qui teste si un arbre binaire est un arbre binaire de recherche en temps linéaire.

Recherche d un élément Rechercher(Arbre A, Element e) 1 if A est vide 2 then return false 3 if Elem(A) = e 4 then return true 5 if e < Elem(A) 6 then 7 if FilsGauche(A) est vide 8 then return false 9 else return Rechercher(FilsGauche(A), e) 10 else 11 if FilsDroit(A) est vide 12 then return false 13 else return Rechercher(FilsDroit(A), e) La recherche d un élément prend un temps au plus de la hauteur de

Rechercher en C typedef struct node { int val; struct node* left; struct node* right; Node, *Tree; int rechercher(tree a, int e) { if (a == NULL) return 0; if (a-> val == e) return 1; if (e < a-> val ) { if (a-> left == NULL) return 0; return rechercher(a->left, e); else { if (a-> right == NULL) return 0; return rechercher(a->right, e);

Ajout d un élément Ajouter(Arbre A, Element e) :Arbre 1 if A est vide 2 then 3 A nouvelle feuille d étiquette e 4 return A 5 if e < Elem(A) 6 then FilsGauche(A) Ajouter(FilsGauche(A), e) 7 else FilsDroit(A) Ajouter(FilsDroit(A), e) 8 return A

Ajouter en C /* renvoie NULL en cas d erreur d allocation */ Tree create_leaf (int val) { return create_node(val, NULL, NULL); void ajouter(tree *a, int n) { if (*a == NULL) { *a = create_leaf(n); return; if (n <= (*a) -> val) { ajouter(&((*a) -> left), n); return; ajouter(&((*a) -> right), n);

Exemple 33 15 47 10 12 20 40

Enlever un élément Enlever(Arbre A, Element e) :Arbre 1 if A est vide 2 then 3 erreur( element non present ) 4 return A 5 if e < Elem(A) 6 then FilsGauche(A) Enlever(FilsGauche(A), e) 7 else if Elem(A) < e 8 then FilsDroit(A) Enlever(FilsDroit(A), e) 9 else 10 A Enlever Racine(A) 11 return A

Enlever en C /* renvoie l adresse du noeud extrait */ /* renvoie NULL en cas d echec */ Tree extract(tree *a, int n) { if (*a == NULL) return NULL; /* ici a est non vide */ if (n < (*a) -> val) { return extract(&((*a)->left), n); if (n > (*a) -> val) { return extract(&((*a)->right), n); /* n == (*a) -> val */ return extract_root(a);

Enlever la racine Enlever Racine(Arbre A) :Arbre 1 if FilsGauche(A) est vide 2 then 3 p A 4 A FilsDroit(A) 5 return p 6 p Enlever Max(FilsDroit(A)) 7 temp Elem(A) 8 Elem(A) Elem(p) 9 Elem(p) temp 10 return p

Enlever la racine en C Tree extract_root(tree *a) { Tree t = NULL; if ((*a) -> left == NULL) { t = *a; *a = (*a) -> right; t -> right = NULL; return t; /* on extrait le max du fils gauche non vide */ t = extract_max(&((*a) -> left)); int tmp = (*a) -> val; (*a) -> val = t -> val; t -> val = tmp; return t;

Enlever le max Enlever Max(Arbre A) :Arbre 1 if FilsDroit(A) est vide 2 then 3 p A 4 A FilsGauche(A) 5 return p 6 return Enlever Max(FilsDroit(A))

Enlever le max en C /* enleve le max sur un arbre non vide */ /* ne renvoiejamais NULL */ Tree extract_max(tree *a) { Tree t = NULL; if ((*a)-> right == NULL) { t = *a; *a = (*a) -> left; t -> left = NULL; return t; return extract_max(&((*a) -> right));

Exemple 33 20 15 47 15 47 10 20 40 50 10 40 50

Temps de calcul Temps de calcul de aouter dans le pire des cas Insertion de 1,2,...,n en O(n/2). Temps moyen d un ajout Insertion successive de i,j : permutation de 1,2,...,n. On considère que toutes les permutations sont équiprobables. P(n) = moyenne du nombre de nœuds par chemin

Temps de calcul i i 1 éléments n i éléments P(n) = 1 n n 1 n + i 1 n i (P(i 1)+1)+ n n (P(n i)+1) i=1 = 1+ 1 n n 2 (i 1)P(i 1)+(n i)p(n i) i=1 = 1+ 2 n 1 n 2 ip(i) i=1 1,39log 2 n

Résolution On va montrer que P(n) = 2(1+ 1 n )H n 3 où H n = 1+ 1 2 +...+ 1 n H n = O(logn) car est le n-ième nombre harmonique. Or n 1 H n 1+ 1 x dx = 1+log e n. On aura donc montré que P(n) = O(logn).

On écrit ou encore P(n) = 1+ 2 n 2 n 2 ip(i)+ 2n 2 n 2 P(n 1) i=1 = 1+ n2 1 n 2 (P(n 1) 1)+ 2n 2 n 2 P(n 1) = n2 1 n 2 P(n 1)+ 2n 1 n 2 n n 1 (P(n)+3) = n+1 n (P(n 1)+3)+ 2 n Comme l expression Q(n) = 2(1+ 1 n )H n = 2 n+1 n H n satisfait la relation de récurrence n n 1 Q(n) = n+1 n Q(n 1)+ 2 n on en déduit que (P(n)+3) Q(n) est une constante. Comme P(1)+3 = Q(1) = 4, on obtient P(n) = Q(n) 3.

File de priorité File de priorité Tas Type abstrait : ensemble d éléments comparables Opérations : Ajouter(E,x), Oter min(e). Implémentations : Listes triées ou non, arbres partiellement ordonnés (tas ou heap, tournois) Un tas (min) est un arbre tel que l étiquette de tout nœud est inférieure ou égale à l étiquette de ses fils.

Implémentation par tas i 0 1 2 3 4 5 6 7 dernier T[i] 3 5 9 6 8 9 10 10 18 9 3 5 9 6 8 9 10 10 18 9

Tas pere(i) = i 1 2 si i > 0 filsgauche(i) = 2i +1 si 2i +1 < dernier filsdroit(i) = 2i +2 si 2i +1 < dernier typedef struct { Element table[max]; int dernier; Tas;

Ajouter un élément Ajouter(Tas t, Element e) :Tas 1 t.dernier t.dernier +1 2 i t.dernier 3 t[i] e 4 while ( i > 0 et t.table[i] < t.table[ i 1 2 ]) 5 do 6 échanger t.table[i] et t.table[ i 1 2 ] 7 i i 1 2 8 return t

Ôter le minimum Oter min(tas t non vide) :Tas 1 t.dernier t.dernier 1, d t.dernier, t[0] t[d +1], i 0 2 fin false 3 while not fin 4 do if 2i +2 d 5 then if t.table[2i +1] < t.table[2i +2] 6 then k 2i +1 7 else k 2i +2 8 if t.table[i] > t.table[k] 9 then échanger t.table[i] et t.table[k] 10 i k 11 else fin true 12 else if 2i +1 = d et t.table[i] > t.table[d] 13 then échanger t.table[i] et t.table[d] 14 else fin true 15 return t

Tri par tas trier(liste lst) : Liste 1 t tas vide 2 for e premier to dernier élément de lst 3 do t Ajouter(t,e) 4 result liste vide 5 while not Vide(lst) 6 do result result +Min(t) 7 t Oter Min(t) 8 return result Temps de calcul O(nlogn) si n est la taille de la liste

Temps de calcul de Entas(i) = O(hauteur(i), de Mise en tas = O(n) Création d un tas Mise en tas(element table[n]) : tas 1 for i n 2 2 to 0 2 do Entas(table[i]) 3 return (table,n 1) Entas(Element table[n], indice i) 1 //les sous-arbres de racine k sont des tas pour i < k n 1 2 if 2i +2 = n ou table[2i +1] table[2i +2] 3 then k 2i +1 4 else k 2i +2 5 if table[i] > table[k] 6 then échanger table[i] et table[k] 7 if k n 2 2 8 then Entas(table, k)

Tas en Java import java.util.priorityqueue; public class Heap { public static void main(string[] args) { Set<Integer> set = new HashSet<Integer>(); set.add(6); set.add(3); set.add(1); set.add(5); set.add(2); set.add(4); PriorityQueue<Integer> heap = new PriorityQueue(set); System.out.println(heap); //[1, 2, 3, 4, 5, 6] for (Integer i:heap){ System.out.print(i+ " "); // 1 2 3 4 5 6 while (! (heap.isempty())){ System.out.print(heap.poll() + " "); // 1 2 3 4 5 6 //poll returns null if this queue is empty.

Arbres équilibrés Dans un ABR les opérations sont en temps O(hauteur(arbre)). Ce temps peut être O(n) où n est le nombre de nœuds. Un arbre équilibré est un arbre où la hauteur de l arbre est proche de logn de telle sorte que les opérations sont en temps O(logn) dans le pire des cas et pas seulement en moyenne. Arbres AVL, arbres rouge-noir, a-b-arbres, etc.

Arbres AVL Définition Un arbre AVL (Adelson-Velsky et Landis) est un arbre binaire de recherche tel que pour chaque nœud les hauteurs du sous-arbre gauche et du sous-arbre droit sont différentes de au plus 1. Définition On appelle balance d un nœud la hauteur du sous-arbre droit moins la hauteur du sous-arbre gauche. Dans un AVL la balance de chaque nœud est 1,0 ou +1. Dans un AVL la hauteur de l arbre est O(logn).

Exemple 50 17 72 12 23 54 76 9 14 19 67

Implémentation On ajoute un attribut aux nœuds qui est la balance ou la hauteur du sous-arbre pour que la balance soit calculée en temps constant. Cet attribut est mis à jour à chaque modification sur un nœud.

Implémentation en C typedef int Element; /* structures pour des arbres AVL */ typedef struct node { Element element; int bal; /* balance of a node 0, 1 or -1*/ struct node * leftchild, * rightchild; Node; typedef struct node * Tree; /* add an element in a balanced tree */ /* returns the (signed) variation of the height */ int addtree(element e, Tree *A);

Ajout d un élément On ajoute un élément comme dans un arbre binaire de recherche. Un des sous-arbres peut devenir déséquilibré de une unité (la balance peut devenir 2 ou +2). On remonte en mettant les hauteurs à jour jusqu à rencontrer un arbre déséquilibré. On ré-équilibre le premier sous-arbre qui devient déséquilibré lors de la remontée. Il devient équilibré avec la même hauteur qu avant l ajout. Il est dont inutile de continuer les ré-équilibrages plus haut.

A 2 B 1 Rotation gauche > A 0 B 0

A 2 B 0 Rotation gauche > A 1 B 0

A 2 C 0 Double rotation gauche > B A 1 0 C 0 B 0

A 2 C 1 Double rotation gauche > B A 1 0 C 0 B 1

A 2 C 1 Double rotation gauche > B A 1 1 C 0 B 0

Ré-équilibrage par rotations et doubles rotations /* entree : A arbre tel que bal(a) = -2 ou +2 */ /* et ses sous-arbres gauche et droit sont AVL */ /* sortie : A arbre AVL */ Tree balance(tree A) { /* called on a nonempty tree A */ if (isemptytree(a)) return A; if (A -> bal == 2) { if (A -> rightchild-> bal >= 0) { /* 0 ou +1 */ /* left rotation*/ return leftrotate(a); else { /* double left */ return doubleleftrotate(a); if (A -> bal == -2) {... return A;

Ajout /* returns the (signed) variation of the height of A, */ int addtree(element e, Tree *A) { int dh; if (isemptytree(*a)) { *A = constree(e,0,emptytree(),emptytree()); return 1; if ((*A) -> element == e) { return 0; if (e > (*A) -> element) { dh = addtree(e,&(*a)->rightchild); else { /* e < (*A) -> element*/ dh = - addtree(e,&(*a)->leftchild);

Ajout suite if (dh == 0) { return 0; else { (*A)-> bal += dh; *A = balance(*a); if ((*A) -> bal == 0) return 0; else return 1;

Rotation gauche Tree leftrotate(tree A) { Tree B = A -> rightchild; int a = A -> bal; int b = B -> bal; A -> rightchild = B -> leftchild; B -> leftchild = A; if (b <= 0) { A-> bal = a - 1 ; else { A-> bal = a - b -1; if (A-> bal >= 0) { /* nouveau a */ B-> bal = b - 1; else { B-> bal = A-> bal + b-1; return B;

Doubles rotations Tree doubleleftrotate(tree A) { A -> rightchild = rightrotate(a -> rightchild); return leftrotate(a); Tree doublerightrotate(tree A) { A -> leftchild = leftrotate(a -> leftchild); return rightrotate(a);