Arbres binaires de recherche optimaux et quasi-optimaux



Documents pareils
ARBRES BINAIRES DE RECHERCHE

Les structures de données. Rajae El Ouazzani

Définitions. Numéro à préciser. (Durée : )

La fonction exponentielle

Quelques Algorithmes simples

1 de 46. Algorithmique. Trouver et Trier. Florent Hivert. Mél : Florent.Hivert@lri.fr Page personnelle : hivert

De même, le périmètre P d un cercle de rayon 1 vaut P = 2π (par définition de π). Mais, on peut démontrer (difficilement!) que

Image d un intervalle par une fonction continue

Algorithmique et Programmation

Chapitre 7. Récurrences

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

Chapitre 3. Quelques fonctions usuelles. 1 Fonctions logarithme et exponentielle. 1.1 La fonction logarithme

1 Recherche en table par balayage

Limites finies en un point

LE PROBLEME DU PLUS COURT CHEMIN

Dualité dans les espaces de Lebesgue et mesures de Radon finies

3 Approximation de solutions d équations

Optimisation non linéaire Irène Charon, Olivier Hudry École nationale supérieure des télécommunications

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

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

I - PUISSANCE D UN POINT PAR RAPPORT A UN CERCLE CERCLES ORTHOGONAUX POLES ET POLAIRES

Arithmétique binaire. Chapitre. 5.1 Notions Bit Mot

Introduction à la théorie des graphes. Solutions des exercices

Exemples de problèmes et d applications. INF6953 Exemples de problèmes 1

Chapitre 5 : Flot maximal dans un graphe

La mesure de Lebesgue sur la droite réelle

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

ÉPREUVE COMMUNE DE TIPE Partie D

Programmation linéaire

Souad EL Bernoussi. Groupe d Analyse Numérique et Optimisation Rabat http ://

Plus courts chemins, programmation dynamique

Les arbres binaires de recherche

Le produit semi-direct

Exercices - Fonctions de plusieurs variables : corrigé. Pour commencer

Probabilités sur un univers fini

Sujet proposé par Yves M. LEROY. Cet examen se compose d un exercice et de deux problèmes. Ces trois parties sont indépendantes.

Continuité et dérivabilité d une fonction

Chp. 4. Minimisation d une fonction d une variable

Eléments de Théorie des Graphes et Programmation Linéaire

ALGORITHMIQUE II NOTION DE COMPLEXITE. SMI AlgoII

Complexité. Licence Informatique - Semestre 2 - Algorithmique et Programmation

Propriétés des options sur actions

I. Polynômes de Tchebychev

Annexe 6. Notions d ordonnancement.

Résolution d équations non linéaires

Cours de Master Recherche

Les indices à surplus constant

Continuité en un point

Sur certaines séries entières particulières

Eteindre. les. lumières MATH EN JEAN Mme BACHOC. Elèves de seconde, première et terminale scientifiques :

La demande Du consommateur. Contrainte budgétaire Préférences Choix optimal

TSTI 2D CH X : Exemples de lois à densité 1

LA PHYSIQUE DES MATERIAUX. Chapitre 1 LES RESEAUX DIRECT ET RECIPROQUE

Chapitre VI - Méthodes de factorisation

I Stabilité, Commandabilité et Observabilité Introduction Un exemple emprunté à la robotique Le plan Problème...

LES TYPES DE DONNÉES DU LANGAGE PASCAL

chapitre 4 Nombres de Catalan

Raisonnement par récurrence Suites numériques

INF601 : Algorithme et Structure de données

Métriques de performance pour les algorithmes et programmes parallèles

La NP-complétude. Johanne Cohen. PRISM/CNRS, Versailles, France.

Développement décimal d un réel

Cours d Analyse. Fonctions de plusieurs variables

Complément d information concernant la fiche de concordance

Baccalauréat ES/L Métropole La Réunion 13 septembre 2013 Corrigé

F411 - Courbes Paramétrées, Polaires

Grandes lignes ASTRÉE. Logiciels critiques. Outils de certification classiques. Inspection manuelle. Definition. Test

Les algorithmes de base du graphisme

Nouvelles propositions pour la résolution exacte du sac à dos multi-objectif unidimensionnel en variables binaires

Calcul différentiel sur R n Première partie

Fonctions de plusieurs variables

La classification automatique de données quantitatives

Comparaison de fonctions Développements limités. Chapitre 10

I. Ensemble de définition d'une fonction

Suites numériques 3. 1 Convergence et limite d une suite

Probabilités sur un univers fini

Programmation linéaire et Optimisation. Didier Smets

MIS 102 Initiation à l Informatique

Théorie et Codage de l Information (IF01) exercices Paul Honeine Université de technologie de Troyes France

TP 2 Réseaux. Adresses IP, routage et sous-réseaux

Précision d un résultat et calculs d incertitudes

Algorithmes d'apprentissage

LES OUTILS D ALIMENTATION DU REFERENTIEL DE DB-MAIN

INTRODUCTION A L ELECTRONIQUE NUMERIQUE ECHANTILLONNAGE ET QUANTIFICATION I. ARCHITECTURE DE L ELECRONIQUE NUMERIQUE

Table des matières. I Mise à niveau 11. Préface

Fibonacci et les paquerettes

CCP PSI Mathématiques 1 : un corrigé

Problèmes de Mathématiques Filtres et ultrafiltres

Architecture des Systèmes d Information Architecture des Systèmes d Information

Soit la fonction affine qui, pour représentant le nombre de mois écoulés, renvoie la somme économisée.

Baccalauréat ES/L Amérique du Sud 21 novembre 2013

CHOIX OPTIMAL DU CONSOMMATEUR. A - Propriétés et détermination du choix optimal

Ordonnancement. N: nains de jardin. X: peinture extérieure. E: électricité T: toit. M: murs. F: fondations CHAPTER 1

III- Raisonnement par récurrence

Algorithmique, Structures de données et langage C

Calcul fonctionnel holomorphe dans les algèbres de Banach

Arbres binaires de recherche

Arbres binaires de décision

LES GENERATEURS DE NOMBRES ALEATOIRES

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

Transcription:

Université Libre de Bruxelles Faculté des Sciences Département d Informatique Arbres binaires de recherche optimaux et quasi-optimaux Mémoire présenté par Gabriel Kalyon en vue de l obtention du grade de Licencié en Informatique. Année académique 2005-2006.

Table des matières 1 Introduction 5 I Fondements et définitions 7 2 Arbres binaires et complexité 8 2.1 Arbres binaires.......................... 8 2.1.1 Définitions......................... 8 2.1.2 Profondeur d un nœud.................. 9 2.1.3 Hauteur d un nœud.................... 9 2.1.4 Rotations......................... 9 2.2 Arbres binaires de recherche................... 11 2.2.1 Modèle........................... 12 2.2.2 Classes d arbres binaires de recherche.......... 13 2.3 Performances asymptotiques................... 14 2.3.1 Notation O(.)....................... 15 2.3.2 Notation Ω(.)....................... 15 2.3.3 Notation Θ(.)....................... 15 2.3.4 Lien entre les notations asymptotiques......... 15 2.4 Complexité............................ 16 2.4.1 Complexité au pire cas.................. 16 2.4.2 Complexité moyenne................... 16 2.4.3 Complexité amortie.................... 17 2.5 Conclusion............................. 18 3 Propriétés des arbres binaires de recherche 19 3.1 Relations entre les propriétés................... 19 3.2 Static finger............................ 19 3.3 Optimalité statique........................ 21 3.4 Working set............................ 21 3.5 Dynamic finger.......................... 22 1

3.6 Unifiée............................... 23 3.7 Optimalité dynamique...................... 24 3.8 Conclusion............................. 25 II Arbres binaires de recherche particuliers 26 4 Arbres Binaires de Recherche Optimaux 27 4.1 Généralités............................ 27 4.2 Algorithme exhaustif....................... 29 4.3 Algorithme de Knuth....................... 29 4.4 Conclusion............................. 31 5 Arbres binaires de recherche équilibrés 32 5.1 Définition............................. 32 5.2 Arbres rouges-noirs........................ 32 5.2.1 Définition......................... 33 5.2.2 Recherche......................... 33 5.2.3 Insertion.......................... 33 5.2.4 Successeur......................... 34 5.2.5 Prédécesseur........................ 35 5.2.6 Analyse des performances................ 35 5.3 Conclusion............................. 36 6 Arbres binaires de recherche auto-ajustables 38 6.1 Définition............................. 38 6.2 Splay trees............................. 38 6.2.1 Splaying.......................... 39 6.2.2 Recherche......................... 39 6.2.3 Insertion.......................... 39 6.2.4 Suppression........................ 39 6.2.5 Analyse des performances................ 40 6.3 Comparaisons........................... 44 6.4 Conclusion............................. 45 III Optimalité dynamique 46 7 Bornes inférieures sur le coût des arbres binaires de recherche 47 7.1 Modèle............................... 47 7.2 La borne inférieure de couverture de rectangle......... 48 7.3 Applications de la borne inférieure de couverture de rectangle 53 2

7.3.1 La borne inférieure d entrelacement........... 54 7.3.2 La seconde borne de Wilber............... 56 7.4 Conclusion............................. 59 8 Tango 60 8.1 Structures de données...................... 60 8.2 Algorithme de l arbre de référence................ 61 8.3 Arbres auxiliaires......................... 66 8.3.1 Définition......................... 66 8.3.2 Concaténation....................... 67 8.3.3 Éclatement........................ 67 8.3.4 Cutting.......................... 69 8.3.5 Joining........................... 72 8.4 Algorithme Tango......................... 75 8.5 Analyse des performances.................... 77 8.6 Conclusion............................. 81 9 Multi-splay tree 82 9.1 Structures de données...................... 82 9.2 Algorithmes............................ 83 9.2.1 Algorithme de l arbre de référence............ 83 9.2.2 Algorithme multi-splay tree............... 83 9.3 Analyse des performances.................... 89 9.3.1 Fonction potentiel..................... 90 9.3.2 Access Lemma Généralisé................ 90 9.3.3 Multi-Splay Access Lemma................ 91 9.3.4 Propriétés......................... 98 9.4 Conclusion............................. 100 10 Optimalité de recherche dynamique 102 10.1 Définition............................. 102 10.2 Intérêt............................... 102 10.3 Structure............................. 103 10.4 Conclusion............................. 108 11 Expérimentations 109 11.1 Jeux de tests........................... 109 11.2 Distribution aléatoire....................... 110 11.3 Distribution working set..................... 111 11.4 Conclusion............................. 112 3

12 Conclusion 114 13 Annexe 116 13.1 Implémentation.......................... 116 13.1.1 Multi-splay trees..................... 116 13.1.2 Splay trees......................... 137 13.1.3 Arbres rouges-noirs.................... 148 13.2 Jeux de tests........................... 158 4

Chapitre 1 Introduction Lorsque nous recherchons un élément dans un ensemble, nous pouvons effectuer deux types de recherche : une recherche linéaire et une recherche dichotomique. La recherche linéaire consiste à examiner un à un les éléments de l ensemble, ce qui ne donne pas des performances intéressantes. La recherche dichotomique consiste à éliminer à chaque étape la moitié des éléments de l ensemble. Cette méthode donne des résultats intéressants, car la recherche se fait en temps logarithmique et non plus en temps linéaire. Les arbres binaires de recherche sont une application de la recherche dichotomique. Ce type de structure organise les éléments sous forme d arbre pour tenter d éliminer à chaque étape de la recherche le plus d éléments possibles (dans le meilleur des cas la moitié des éléments sont éliminés) de manière à localiser le plus rapidement possible un élément. Depuis que ce type de structure a été développé dans les années 1960, il y a eu énormément de travaux réalisés sur le sujet. En général, le but de ces travaux était d essayer de développer une structure qui atteigne l optimalité dynamique, c est-à-dire qui donne le meilleur coût de recherche et cela quelle que soit la séquence d éléments à rechercher. Ce mémoire consiste en un travail de recherche bibliographique et le but est de présenter les principaux travaux réalisés dans le domaine des arbres binaires de recherche et de l optimalité dynamique, ainsi que les principales étapes franchies dans ces domaines. Cela va en général consister à présenter des structures et à analyser leurs performances. La présentation de ces résultats se fera de manière plus détaillée et plus didactique que dans les articles dans lesquels ils sont présentés. Le second objectif de ce mémoire est d implémenter quelques structures de données pour vérifier si en pratique nous obtenons des résultats aussi intéressants qu en théorie. En effet, il se peut que pour des structures trop complexes les résultats obtenus en pratique soient moins bons que ceux auxquels nous aurions pu nous attendre à avoir 5

par la théorie. Ceci s explique notamment par le fait que dans les analyses des coûts d une structure, nous omettrons les constantes multiplicatives et les termes d ordre inférieur. Dans les chapitres 2 et 3, nous allons définir un certain nombre de notions. En fait, dans le chapitre 2, nous allons définir des notions de base dans le domaine des arbres binaires de recherche et dans le chapitre 3, nous allons définir des propriétés permettant de caractériser le coût d exécution d une séquence d accès dans un arbre binaire de recherche. Parmi ces propriétés, nous pouvons notamment citer l optimalité statique et l optimalité dynamique. Dans le chapitre 4, nous allons étudier les arbres binaires de recherche optimaux. Cette structure se base sur une connaissance préalable de la distribution des clés à accéder pour atteindre l optimalité statique. Dans les chapitres 5 et 6, nous allons présenter deux catégories d arbres binaires de recherche : les arbres binaires de recherche équilibrés et les arbres binaires de recherche auto-ajustables. Chacune de ces catégories sera illustrée par une structure de données : les arbres rouges-noirs pour la première et les splay trees pour la seconde. Nous détaillerons les algorithmes de ces structures et nous analyserons leurs performances. Dans le chapitre 7, nous présenterons trois bornes inférieures sur le coût d exécution d une séquence d accès dans un arbre binaire de recherche. Une de ces trois bornes est la borne inférieure d entrelacement. Celle-ci est à la base de la structure Tango étudiée dans le chapitre 8. Cette structure présente un grand intérêt, parce qu elle approche l optimalité dynamique à un facteur log(log n) près. Dans le chapitre 9, nous étudierons la structure des multi-splay trees, qui approche également l optimalité dynamique à un facteur log(log n) près. Cette structure présente comme principal intérêt d être plus facile à implémenter que Tango. À l heure actuelle, aucune structure de données n atteint l optimalité dynamique, mais nous présenterons dans le chapitre 10 un cas particulier où cette propriété est atteinte. Nous montrerons dans ce chapitre, que nous pouvons atteindre l optimalité dynamique en changeant le modèle de coût et en permettant à la structure d effectuer un nombre quelconque d opérations de réorganisation entre chaque accès sans que cela soit comptabilisé dans le coût d exécution. Pour analyser les performances en pratique des structures étudiées, nous en avons implémenté certaines pour y exécuter des jeux de tests. Dans le chapitre 11, nous fournirons les résultats des jeux de tests exécutés, ainsi que les conclusions que nous pouvons en tirer. L implémentation des structures, accompagnée d explications, est fournie en annexe. 6

Première partie Fondements et définitions 7

Chapitre 2 Arbres binaires et complexité Dans ce chapitre, nous allons définir toute une série de notions de base dans le domaine des arbres binaires de recherche et dans le domaine de la complexité. Ces rappels seront utiles au lecteur de manière à poser ces notions, qui seront sans cesse utilisées. 2.1 Arbres binaires Dans cette section, nous allons donner la définition d un arbre binaire, ainsi que de la terminologie associée à ce type de structure. 2.1.1 Définitions Cette section est basée sur les notes d un cours dispensé par Olivier Markowitch [Mar02]. Un arbre est une structure de données permettant de stocker un ensemble d éléments et il consiste en une collection de nœuds et d arêtes (on utilisera aussi le terme arc pour désigner une arête). Un nœud permet de stocker un élément de cet ensemble et une arête (arc) est un lien entre deux nœuds. L organisation de l arbre est telle que deux nœuds quelconques de l arbre sont reliés entre eux par un chemin unique. Un chemin est une suite de nœuds distincts dans laquelle deux nœuds successifs sont reliés par une arête. Un nœud peut posséder des fils. Un nœud y est le fils d une nœud x si y se situe en-dessous de x dans l arbre et s il est relié à ce nœud par une arête. Un nœud x possède également un père ; il s agit du nœud ayant x comme fils. Les nœuds qui n ont pas de fils sont appelés des feuilles. Le nœud au sommet de l arbre est appelé la racine et il ne possède pas de père. 8

Un arbre binaire est un arbre, où chaque nœud possède au plus deux fils appelés fils gauche et fils droit. Les ancêtres d un nœud x sont les nœuds qui appartiennent au chemin reliant la racine de l arbre à x. Les descendants d un nœud x sont les nœuds qui ont x comme ancêtre. Le sous-arbre d un nœud x dans un arbre A est la partie de A contenant x, ainsi que ses descendants. Le sous-arbre gauche d un nœud x est le sousarbre du fils gauche de x. Le sous-arbre droit d un nœud x est le sous-arbre du fils droit de x. Un sous-arbre est vide s il ne contient pas d éléments ; par exemple si x n a pas de fils droit, alors le sous-arbre droit de x est vide. 2.1.2 Profondeur d un nœud Cette section est basée sur les notes d un cours dispensé par Olivier Markowitch [Mar02]. La profondeur d un nœud x, notée d(x), est le nombre d arcs sur le chemin allant de la racine de l arbre au nœud x plus 1. De manière plus formelle : 1. d(x) = 1 si x est la racine de l arbre 2. d(x) = 1 + d(parent) sinon où parent est le nœud père de x. 2.1.3 Hauteur d un nœud Cette section est basée sur les notes d un cours dispensé par Olivier Markowitch [Mar02]. La hauteur d un nœud x, notée h(x), est le nombre d arcs sur le chemin allant de x à la feuille la plus profonde du sous-arbre de x. De manière plus formelle : 1. h(x) = 0 si x est feuille 2. h(x) = 1 + maxh(fg),h(fd) sinon où fg et fd sont, respectivement, les fils gauche et droit de x. 2.1.4 Rotations Il existe trois types de rotations possibles sur les arbres binaires : 1. une rotation simple 2. une rotation double 3. une rotation zig-zig 9

Fig. 2.1 Rotation simple entre x et y. 2.1.4.1 Rotation simple Cette opération a été décrite pour la première fois dans l article d Adel son-vel skii et Landis [AVL62]. Une rotation simple entre un nœud x et un nœud y (avec d(x) >d(y), où d(x) est la profondeur de x et d(y) est la profondeur de y) consiste à permuter la profondeur de x et de y comme décrit à la figure 2.1. Une rotation simple est dite droite si x est le fils gauche de y et elle dite gauche si x est le fils droit de y. La rotation à la figure 2.1 correspond à une rotation droite. La rotation gauche est déduite de manière symétrique par rapport à la rotation droite. 2.1.4.2 Rotation double Une rotation double entre un nœud x, un nœud y et un nœud z (avec d(x) >d(y) >d(z)) consiste à effectuer une rotation simple entre x et y, puis une rotation simple entre x et z (cfr figure 2.2). Pour pouvoir effectuer une rotation double, il faut que x soit un fils droit (respectivement fils gauche) et y soit un fils gauche (respectivement fils droit). 10

Fig. 2.2 Rotation double entre x, y et z. 2.1.4.3 Rotation zig-zig Cette opération a été décrite pour la première fois dans l article de Sleator et Tarjan [ST85]. Une rotation zig-zig entre un nœud x, un nœud y et un nœud z (avec d(x) >d(y) >d(z)) consiste à permuter la profondeur de x et de z comme décrit à la figure 2.3. Pour pouvoir effectuer une rotation zig-zig, il faut que x et y soient tous deux des fils gauches ou des fils droits. 2.2 Arbres binaires de recherche Le point principal dans cette section consiste à définir le modèle des arbres binaires de recherche, qui sera étudié. Il faut noter, qu il existe plusieurs modèles d arbres binaires de recherche. En général, ces variantes sont équivalentes (à un facteur constant près) en terme de performances au modèle décrit ci-dessous. 11

2.2.1 Modèle Fig. 2.3 Rotation zig-zig entre x, y et z. Nous considérons le modèle défini par Demaine, Harmon, Iacono et Patrascu [DHIP04]. Ils ont défini ce modèle en se basant sur celui de Wilber [Wil89], qui correspond également à celui utilisé par Sleator et Tarjan [ST85]. Un ABR(Arbre Binaire de Recherche) est un arbre binaire qui maintient un ensemble de clés selon une règle précise : pour chaque nœud x de l arbre, la clé de x est plus grande que toutes les clés contenues dans le sous-arbre gauche de x et elle est plus petite que toutes les clés contenues dans le sousarbre droit de x. Dans cette définition, nous considérons qu un ABR ne supporte qu une seule opération : la recherche d un élément. Cette recherche se fait sur un ensemble statique de n clés. Nous considérons seulement des recherches réussies, appelées accès. Nous supposons également, sans nuire à la généralité, que chaque clé d un ABR prend une valeur unique dans l ensemble 1, 2,..., n. Un ABR est utilisé pour servir une séquence d accès, qui consiste en une suite de clés X = x 1,x 2,..., x m. L algorithme d accès de l ABR permet, en fait, de servir chaque accès x i de cette séquence. Pour accéder à un nœud x i, l algorithme d accès ne peut utiliser qu un seul pointeur P durant le parcours de l arbre. Au début de l accès, ce pointeur est initialisé à la racine de l arbre. 12

L algorithme d accès peut, ensuite, réaliser les opérations de coût unitaire suivantes : 1. déplacer le pointeur P vers son fils gauche 2. déplacer le pointeur P vers son fils droit 3. déplacer le pointeur P vers son père 4. effectuer une rotation simple entre le pointeur P et son père L algorithme d accès réalise une séquence des opérations ci-dessus jusqu à ce que le pointeur P atteigne le nœud x i. Le coût d accès au nœud x i est le nombre d opérations de coût unitaire réalisées pour l atteindre. Dès lors, le coût exigé par un ABR pour exécuter une séquence X = x 1,x 2,..., x m vaut m i=1 cout(x i). Nous désignerons ce modèle par le terme modèle dynamique. Comme autre modèle pour les arbres binaires de recherche, nous pouvons citer le modèle standard. Ce modèle est défini dans les articles [DSW05] et [BCK03] et il sera abordé dans le chapitre 10. 2.2.2 Classes d arbres binaires de recherche Il existe deux grandes classes d ABR, basées sur la manière de choisir l opération de coût unitaire suivante à réaliser lors d un accès x i : 1. les ABR online 2. les ABR offline 2.2.2.1 ABR online Un ABR online [DHIP04] est une structure de données ABR dans laquelle chaque nœud peut contenir des données supplémentaires. Lors de chaque opération de coût unitaire, les données contenues dans le nœud pointé par le pointeur P peuvent être modifiées. Les données contenues dans les nœuds permettent, en général, de garder de l information sur les clés déjà accédées, de manière à améliorer le coût d accès aux clés devant encore être accédées. Lors d un accès, l algorithme d accès choisit l opération de coût unitaire suivante à réaliser en fonction de la clé à accéder et des informations supplémentaires contenues dans le nœud pointé par le pointeur P. La quantité d informations supplémentaires contenues dans un nœud doit être la plus petite possible de manière à avoir une incidence négligeable sur le temps d exécution du programme. En effet, si cette quantité est trop grande, la mise à jour de ces informations après une opération risque de coûter cher. 13

Comme exemples d ABR online, nous pouvons citer : les arbres rougesnoirs (qui nécessitent un bit de couleur par nœud), les arbres AVL (qui nécessitent un compteur par nœud) et les splay trees (qui ne nécessitent pas d informations supplémentaires). 2.2.2.2 ABR offline Un ABR offline est une structure de données ABR, qui a une connaissance préalable de la séquence X à exécuter. En fait, il s agit d une structure utopique, qui avant même de servir X, connaît déjà les nœuds qui devront être accédés dans cette séquence. De par cette connaissance, une telle structure n a pas besoin de garder des informations supplémentaires dans ses nœuds. Lors d un accès x i, le choix de l opération de coût unitaire suivante à réaliser est basé sur la connaissance de toute la séquence X. La différence entre un ABR online et un ABR offline est que, pour choisir l opération de coût unitaire suivante à réaliser lors d un accès x i, ce dernier peut se baser sur les accès qui suivent x i dans la séquence X. 2.3 Performances asymptotiques Cette section est basée sur l ouvrage de Flajolet et Sedgewick [FS98]. Pour caractériser l efficacité d un algorithme, nous étudions ses performances asymptotiques. Ceci consiste à étudier la façon dont varie le temps d exécution d un algorithme quand la taille de l entrée tend vers l infini. Plusieurs raisons justifient l usage des méthodes asymptotiques : 1. les performances asymptotiques d un algorithme sont plus faciles à calculer que son temps d exécution exact. 2. calculer le temps d exécution exact d un algorithme est en général inutile. En effet, pour des entrées suffisamment grandes, les effets des constantes multiplicatives et des termes d ordre inférieur dans le temps d exécution exact sont négligeables. 3. les méthodes asymptotiques fournissent de bons critères de comparaison entre les algorithmes. En effet, un algorithme, qui est asymptotiquement meilleur qu un autre, est plus efficace que ce dernier pour des entrées suffisamment longues. Ci-dessous suivent trois notations asymptotiques permettant de décrire le temps d exécution asymptotique d un algorithme. 14

2.3.1 Notation O(.) Soit N la taille de l entrée d un algorithme. Nous disons que le temps d exécution T (N) d un algorithme est en O(g(N)) (dit grand o de g de N ) s il existe des constantes positives c 1 et n 0 telles que : n n 0, 0 T (n) c 1.g(n) (2.1) Nous constatons, que pour n suffisamment grand, T (n) est borné supérieurement par c 1 g(n). Intuitivement, la notation O(.) sert à majorer la fonction T (N). 2.3.2 Notation Ω(.) Soit N la taille de l entrée d un algorithme. Nous disons que le temps d exécution T (N) d un algorithme est en Ω(g(N)) (dit grand omega de g de N ) s il existe des constantes positives c 1 et n 0 telles que : n n 0, 0 c 1.g(n) T (n) (2.2) Nous constatons, que pour n suffisamment grand, T (n) est borné inférieurement par c 1 g(n). Intuitivement, la notation Ω(.) sert à minorer la fonction T (N). 2.3.3 Notation Θ(.) Soit N la taille de l entrée d un algorithme. Nous disons que le temps d exécution T (N) d un algorithme est en Θ(g(N)) (dit grand theta de g de N ) s il existe des constantes positives c 1, c 2 et n 0 telles que : n n 0, 0 c 1.g(n) T (n) c 2.g(n) (2.3) Nous constatons, que pour n suffisamment grand, T (n) est borné inférieurement par c 1 g(n) et supérieurement par c 2 g(n). Intuitivement, la notation Θ(.) fournit une valeur approchée de la fonction T (N). 2.3.4 Lien entre les notations asymptotiques Une fois les trois définitions ci-dessus présentées, il est assez aisé d établir un lien entre elles. Ce lien est explicité par le théorème suivant. Théorème 1. Pour deux fonctions quelconques g(n) et f(n), nous avons que f(n) = Θ(g(n)) si et seulement si f(n) = O(g(n)) et f(n) = Ω(g(n)). 15

Ce théorème peut facilement être démontré en prouvant d abord l implication du théorème dans un sens, puis en prouvant son implication dans l autre sens et cela en se basant à chaque fois sur la définition de O(.), Θ(.) et Ω(.) 2.4 Complexité Cette section est basée sur l ouvrage de Jean Cardinal [Car04] et l article de Tarjan [Tar85]. Il existe principalement trois manières d analyser la complexité d une structure : 1. effectuer une analyse au pire cas 2. effectuer une analyse amortie 3. effectuer une analyse du cas moyen Dans cette section, nous allons définir ces trois analyses et développer de manière plus précise l analyse amortie. 2.4.1 Complexité au pire cas L analyse au pire cas consiste à caractériser la complexité d une opération dans le pire des cas. Ce pire cas peut se produire de manière répétée ou non. Si ce pire cas peut se produire de manière répétée, la complexité au pire cas donne une bonne indication des performances en pratique de la structure. Par contre, si ce pire cas ne peut pas se produire souvent, elle ne donne pas une indication concrète sur les performances en pratique. Ceci peut être illustré par l exemple suivant : la complexité au pire cas de l algorithme de Knuth-Morris-Pratt (pour la recherche de motifs) est bien meilleure que la complexité au pire cas de l algorithme de Boyer-Moore, alors qu en pratique ce deuxième algorithme est plus efficace que le premier. 2.4.2 Complexité moyenne L analyse de la complexité moyenne est en général délicate. La complexité moyenne est calculée sur la base d une distribution de probabilités sur l ensemble des entrées de l algorithme, pour laquelle des hypothèses ont été posées. La source de l aléatoire vient alors des entrées. Cette complexité donne des informations assez significatives concernant les performances en pratique si les pire cas sont rares. 16

Il existe une seconde manière de calculer une complexité moyenne, dans laquelle la source de l aléatoire ne vient pas des entrées, mais de l algorithme qui fait des choix aléatoires. La complexité est calculée sur ces choix et on parle alors de complexité moyenne randomisée. 2.4.3 Complexité amortie 2.4.3.1 Définition La complexité amortie est la complexité au pire cas d une séquence de M opérations divisée par M. La complexité amortie donne des informations significatives concernant les performances en pratique d une structure, tout en se basant sur les performances au pire cas. Cette analyse apparaît, donc, comme un bon intermédiaire entre la complexité moyenne et la complexité au pire cas. Elle permet, mieux que les deux analyses précédentes, de concevoir des structures efficaces en pratique. Il existe plusieurs méthodes pour effectuer une analyse amortie d une structure. La méthode qui sera développée dans le point suivant est la méthode du potentiel. 2.4.3.2 Méthode du potentiel La méthode du potentiel nécessite de définir une fonction potentiel. Cette fonction peut être comparée à un compte bancaire. Celui-ci ne peut pas descendre en dessous d une certaine valeur (par exemple 0). Lorsqu un achat nécessite un coût moindre que prévu, l argent restant est remis dans le compte et celui-ci augmente. Par contre, lorsque le coût d un achat est supérieur à celui prévu, il faut aller puiser dans le compte pour payer le reste et celui-ci diminue donc. Cette analogie permet de donner une première idée de ce qu est une fonction potentiel. Une définition plus précise est donnée ci-dessous. La fonction potentiel est une valeur qui est bornée inférieurement par une constante. Cette borne dépend de la structure, mais vaut en général 0. La fonction potentiel va augmenter, lorsque le temps réel pour effectuer une opération est inférieur à son temps amorti. Et elle va diminuer, si le temps réel pour effectuer une opération est supérieur à son temps amorti. En d autres termes, lorsque le coût effectif d une opération est inférieur à son coût amorti, la fonction potentiel sauvegarde la différence entre ces deux coûts, et lorsque le coût d une opération est supérieur à son coût amorti, la fonction potentiel puise dans sa réserve pour compenser ce surcoût. 17

Pour prouver une complexité amortie C A, il faut établir l équation suivante, qui utilise une fonction potentiel P : C A = C E + P, (2.4) où C E est la complexité effective de l opération et P est la variation de la fonction potentiel entre le début et la fin de l opération. Pour établir l équation ci-dessus, il faut prouver, qu à la ième ( 1 i M) opération d une séquence de M opérations, l égalité suivante est vérifiée : C A = C E (i)+ P (i), (2.5) où C E (i) est le coût effectif de la ième opération et P (i) est la variation de potentiel à la ième étape, c est-à-dire la différence entre le potentiel après la ième étape (= P (i)) et le potentiel avant la ième étape (= P (i 1)). Cette équation peut être réécrite de la manière suivante : 2.5 Conclusion C A = C E (i)+p (i) P (i 1) (2.6) Dans ce chapitre, nous avons d abord défini la notion d arbre binaire, ainsi que la terminologie associée à ce type de structure. Ensuite, nous avons défini le modèle dynamique des arbres binaires de recherche. Et finalement, nous avons présenté plusieurs outils (les performances asymptotiques et les différents types de complexité) permettant de caractériser les performances d une structure ABR et permettant de comparer les performances de telles structures. 18

Chapitre 3 Propriétés des arbres binaires de recherche Dans ce chapitre, nous allons présenter plusieurs propriétés caractérisant le coût d exécution d une séquence d accès dans des ABR. Ces propriétés sont également valables pour certaines structures qui ne sont pas des ABR. 3.1 Relations entre les propriétés Nous allons décrire dans ce chapitre six propriétés : 1. Static Finger 2. Optimalité Statique 3. Working Set 4. Dynamic Finger 5. Unifiée 6. Optimalité Dynamique La figure 3.1 illustre la relation d implication entre ces propriétés. La propriété static finger est la plus faible de toutes, car elle est une conséquence de toutes les autres propriétés. De plus, les propriétés working set et dynamic finger sont indépendantes. Les définitions des propriétés ci-dessus sont basées sur deux articles de Iacono [Iac01] et [Iac05]. 3.2 Static finger Considérons un ensemble de n clés 1, 2,..., n, une séquence d accès X = x 1,x 2,..., x m et un nœud spécifique f, appelé le finger, appartenant à 19

Fig. 3.1 Relation d implication entre les propriétés. l ensemble 1, 2,..., n. Une structure a la propriété static finger si le coût total pour exécuter la séquence X vaut : ( m ) O log (1 + x i f ) (3.1) i=1 L expression x i f est la distance dans l ordre symétrique entre le finger f et le nœud x i. En d autres termes, la distance x i f est le nombre d éléments situés entre x i et f dans la séquence triée des nœuds plus 1. Une fois fixé, le finger reste le même durant toute l exécution de la séquence X. Les Finger Search Trees [BLM + 03] possèdent cette propriété, mais cette structure ne répond pas à la définition du modèle dynamique des ABR (cfr point 2.2.1), car son opération de recherche peut débuter à partir d une feuille quelconque de l arbre. Les splay trees [ST85] possèdent également cette propriété. De l équation (3.1), nous constatons que plus la distance entre le finger f et le nœud x i est petite, plus le coût sera petit et inversement. Par conséquent, pour une structure ayant la propriété static finger, le coût total pour exécuter une séquence X sera déterminé par la distance dans l ordre symétrique entre le finger f et chaque nœud de la séquence X à exécuter. 20

3.3 Optimalité statique Considérons un ensemble de n clés 1, 2,..., n et une séquence d accès X = x 1,x 2,..., x m. Une structure a la propriété d optimalité statique, si elle exécute X avec un coût de : O ( n i=1 ( ) ) m f (i) log, (3.2) f (i) où f (i) est le nombre d accès à i dans la séquence X. Supposons que nous ayons une variable aléatoire discrète qui puisse prendre n valeurs ( 1, 2,..., n ), l entropie de cette variable est la quantité : H = n p i log (p i )= i=1 n i=1 ( ) 1 p i log, (3.3) p i où p i est la probabilité que la variable aléatoire soit égale à i. Prenons l équation (3.2) et réécrivons-la de la manière suivante : ( n ( ) ) f(i) m O m m log (3.4) f(i) i=1 En posant p i = f(i)/m, nous obtenons : ( n ( ) ) 1 O m p i log = O(m H) (3.5) p i i=1 Une structure, qui atteint l optimalité statique, exécute donc la séquence X avec un coût égal à O(m H). De plus, elle exécute un accès avec un coût amorti O(H). Les Arbres Binaires de Recherche Optimaux [Knu73] et les splay trees [ST85] sont deux structures ABR ayant cette propriété d optimalité statique. Ces deux structures feront l objet d explications plus détaillées, respectivement, dans les chapitres 4 et 6. 3.4 Working set Considérons un ensemble de n clés 1, 2,..., n et une séquence d accès X = x 1,x 2,..., x m. Soit l(i, x)égal à j si x j est le dernier accès à x dans la séquence x 1,x 2,..., x i 1. Si x n est pas accédé dans cette séquence, alors l(i, x) vaut 1. Nous définissons w(i, x) comme étant le nombre d éléments distincts accédés dans 21

la séquence x l(i,x)+1,x l(i,x)+2,..., x i. Dès lors, w(i, x i ) est le nombre d éléments distincts accédés dans la séquence x l(i,xi )+1,x l(i,xi )+2,..., x i. Il s agit donc du nombre d éléments distincts accédés entre l accès x i et le précédent accès à cet élément. Notons w(i, x i ) par w(x i ). Une structure a la propriété working set, si elle exécute une séquence d accès X avec un coût : ( m ) O log (w (x i )) (3.6) i=1 De cette propriété, nous déduisons que plus il y a d éléments différents accédés entre deux accès successifs d un nœud x i, plus le coût d accès à ce nœud x i sera élevé et inversement. De plus, nous constatons que, si les accès d une séquence X ne se font que sur un sous-ensemble de k éléments parmi les n, la complexité d un accès à une clé x i de cette séquence sera d au plus O(log k), car w(x i ) ne pourra jamais être supérieur à k. Par conséquent, pour une structure ayant la propriété working set, le coût total pour exécuter une séquence X dépend de deux critères : 1. le nombre de clés différentes dans la séquence X. 2. le nombre d éléments différents accédés entre deux accès successifs d une même clé dans la séquence X. Plus la première quantité sera petite, plus elle aura d importance dans le coût d exécution de la séquence X. En fait, cette propriété est basée sur la localité temporelle : plus la localité temporelle entre deux accès successifs d une même clé est petite (c est-à-dire que le temps écoulé entre ces deux accès est petit), plus le coût d accès à ce nœud est petit et inversement. La Working Set Data Structure proposée par Iacono [Iac01] atteint un pire cas de O(log(w(x i ))) pour un accès x i. Cependant, cette structure ne répond pas à la définition du modèle dynamique des ABR, car elle utilise des pointeurs et des files additionnels. Les splay trees [ST85] possèdent également cette propriété. 3.5 Dynamic finger Considérons un ensemble de n clés 1, 2,..., n et une séquence d accès X = x 1,x 2,..., x m. Une structure a la propriété dynamic finger si le coût total pour exécuter la séquence X vaut : 22

O ( m 1 i=1 log (1 + x i+1 x i ) ) (3.7) Cette propriété est analogue à la propriété static finger. La différence étant que pour cette dernière, le finger f est fixe, tandis que pour la propriété dynamic finger, le finger est le dernier élément accédé. Les Level-Linked Trees [BT80] possèdent cette propriété, mais cette structure ne répond pas à la définition du modèle dynamique des ABR, car elle utilise des pointeurs additionnels. Les level-linked trees atteignent un pire cas de O(log (1 + x i+1 x i )) pour un accès. Les splay trees [ST85] possèdent également la propriété dynamic finger. De l équation (3.7), nous déduisons que l accès à un nœud est d autant plus rapide que la distance entre l élément auquel on doit accéder et le dernier élément auquel on a accédé est petite. En fait, cette propriété est basée sur la localité spatiale : plus la distance entre deux accès adjacents est petite, plus le coût d accès au nœud est petit et inversement. Par conséquent, pour une structure ayant la propriété dynamic finger, le coût total pour exécuter une séquence X sera déterminé par la distance entre les accès adjacents de la séquence. Plus la distance entre les accès adjacents de la séquence sera grande, plus le coût pour exécuter X sera grand et inversement. 3.6 Unifiée Considérons un ensemble de n clés 1, 2,..., n et une séquence d accès X = x 1,x 2,..., x m. Une structure a la propriété unifiée si elle exécute X avec un coût : ( m ) O min (log (w(i, j)+ x i j + 1)) (3.8) j X i=1 L Unified Structure [Iac01] possède cette propriété, mais elle ne répond pas à la définition du modèle dynamique des ABR. Les splay trees [ST85] sont conjecturés avoir la propriété unifiée. À l heure actuelle, il n existe aucune structure ABR qui atteigne cette borne. Une structure ayant cette propriété exécutera une séquence avec un coût faible si les accès sont proches en terme de distance à des éléments accédés récemment et inversement. Cette propriété est donc basée sur la localité temporelle et la localité spatiale des accès. 23

La propriété unifiée implique la propriété working set et la propriété dynamic finger. L intérêt de la propriété unifiée est d unifier les propriétés working set et dynamic finger ; ces deux propriétés étant indépendantes, car aucune des deux n implique l autre. 3.7 Optimalité dynamique Considérons une séquence quelconque d accès X = x 1,x 2,..., x m. Certains ABR peuvent l exécuter de manière optimale. Notons par OP T (X) ce coût minimal pour exécuter X. Ce coût OP T (X) est le coût de l ABR offline le plus rapide qui puisse exécuter X. En effet, dans le modèle ABR offline, il n y a aucune contrainte dans l algorithme d accès sur la manière de choisir la prochaine opération de coût unitaire à réaliser. Et en particulier, ce choix peut dépendre des futurs accès à servir dans la séquence. Une structure de données ABR a la propriété d optimalité dynamique, si elle exécute une quelconque séquence d accès X avec un coût O(OP T (X)). On dit qu une structure de données A est α compétitive (ou a un taux de compétitivité de α) si pour toute séquence X : COUT A (X) α OP T (X), (3.9) où COUT A (X) est le coût nécessaire à la structure A pour exécuter X. La conjecture d optimalité dynamique, énoncée par Sleator et Tarjan [ST85], affirme que les splay trees sont O(1) compétitif s. Cependant, aucune démonstration n est venue étayer cette conjecture. Jusqu il y a peu, le meilleur taux de compétitivité était le taux trivial de O(log(n)), atteint par exemple par les arbres rouges-noirs. Ce n est qu en 2004, que ce taux a pu être amélioré par une structure de données appelée Tango [DHIP04]. Cette structure atteint un taux de compétitivité de O(log(log n)). Par après, une autre structure de données, les Multi-Splay Trees ([SW04] et [DSW06]), a été développée sur base de Tango pour atteindre également un taux de compétitivité de O(log(log n)). Ces deux structures seront détaillées dans les chapitres 8 et 9. La propriété d optimalité dynamique a une signification profonde : connaître le futur ne permet d améliorer le temps d exécution d une séquence d accès que d un facteur constant. En effet, si nous parvenons à développer un ABR online, qui atteint l optimalité dynamique, cela signifierait que nous sommes parvenus à créer une structure, qui en se basant sur le passé de la séquence d accès X à exécuter, donne des résultats équivalents, à un facteur constant près, à la meilleure structure de données offline, qui se base sur la 24

connaissance du futur pour exécuter de manière optimale la séquence d accès X. 3.8 Conclusion Dans ce chapitre, nous avons défini toute une série de propriétés permettant de caractériser le coût d exécution d une séquence d accès dans un ABR. La propriété la plus forte étant bien évidemment l optimalité dynamique. De plus, nous avons présenté la relation d implication entre ces propriétés de manière à spécifier celles qui sont les plus fortes et celles qui sont les plus faibles. 25

Deuxième partie Arbres binaires de recherche particuliers 26

Chapitre 4 Arbres Binaires de Recherche Optimaux La rédaction de ce chapitre est basée sur l ouvrage de Knuth [Knu73]. La structure des ABRO (= Arbres Binaires de Recherche Optimaux) a été développée par Knuth [Knu73]. Le but de cette structure est d atteindre l optimalité statique et elle nécessite pour cela de connaître la distribution des clés à accéder. Pour rappel, une structure a la propriété d optimalité statique (cfr point 3.3), si elle exécute une séquence d accès X = x 1,x 2,..., x m sur un arbre de n clés 1, 2,..., n avec un coût de : O ( n i=1 ( ) ) m f (i) log, (4.1) f (i) où f (i) est le nombre d accès à i dans la séquence X. 4.1 Généralités Pour construire l ABRO d un ensemble de nœuds P = p 1,p 2,..., p n, nous disposons, en plus de ces nœuds, de leur fréquence relative d accès. Pour tenir compte des recherches infructueuses, nous avons également besoin d un ensemble de nœuds externes Q = q 0,q 1,q 2,..., q n. Ces nœuds externes représentent les pointeurs nuls des nœuds de l arbre. Chaque nœud de Q représente un intervalle de nœuds pour lesquels la recherche est infructueuse : q 0 représente l intervalle (,p 1 ), q i représente l intervalle (p i,p i+1 )( 0 < i<n) et q n représente l intervalle (p n, ). Les nœuds de Q sont accompagnés de leur fréquence relative d accès. 27

Fig. 4.1 Arbre dont le coût de recherche est de 2.2 Le coût d une recherche dans l arbre T construit sur les clés de P est donné par la quantité : c(t )= ( 1 j n f(p j ) profondeur(p j ) ) + ( 0 j n f(q j ) (profondeur(q j ) 1) où f(p j ) est la fréquence relative d accès au nœud p j et où f(q j ) est la fréquence relative d accès au nœud externe q j, c est-à-dire la probabilité que la clé recherchée appartienne à l intervalle (q j,q j+1 ). La notion de profondeur est définie au point 2.1.2. Considérons l arbre T de la figure 4.1 et l assignation de fréquences suivante : f(p 1 ) = 0.15, f(p 2 ) = 0.1, f(p 3 ) = 0.25, f(q 0 ) = 0.05, f(q 1 ) = 0.2, f(q 2 )=0.15, f(q 3 )=0.1. Le coût d une recherche dans l arbre T est le suivant : ), c(t ) = (0.15) 3 + (0.1) 2 + (0.25) 1 + (0.05) 3 +(0.2) 3 + (0.15) 2 + (0.1) 1 = 2.2 Pour déterminer l ABRO de P, il suffit de trouver l arbre T, dont le coût de recherche c(t ) est le minimum parmi les coûts de recherche de tous les arbres possibles. À noter qu il peut exister plusieurs arbres, dont le coût de recherche est minimal. 28

4.2 Algorithme exhaustif Pour déterminer l ABRO de l ensemble P de nœuds, il suffit de construire tous les arbres possibles sur P, de calculer leur coût de recherche et de retenir celui dont le coût est minimal. Cependant, la complexité d un tel algorithme est exponentielle. En effet, avec n nœuds il est possible de construire C n+1 (= le (n + 1)ème nombre de Catalan) arbres binaires de recherche. Or, C n+1 = ( 2n n ) (n + 1) 4 n π 1/2 n 3/2 Clairement un tel algorithme pour construire l ABRO est à exclure. 4.3 Algorithme de Knuth L algorithme de Knuth est un algorithme de programmation dynamique. Il se base sur la propriété suivante : tous les sous-arbres d un ABRO sont optimaux. En effet, une amélioration du coût de recherche d un quelconque sous-arbre d un ABRO mène à une amélioration du coût de recherche de l ABRO. L idée est de considérer le problème de manière récursive (cfr figure 4.2). Un ABRO T est constitué d une racine p k, d un sous-arbre gauche (qui est un ABRO) et d un sous-arbre droit (qui est un ABRO). On construit de manière récursive le sous-arbre gauche et le sous-arbre droit de p k avant de construire T. Pour construire l ABRO avec l algorithme de programmation dynamique, nous avons besoin de trois tables : 1. la table C, où C(i, j) ( 0 i j n) est le coût de l ABRO sur les nœuds p i+1,..., p j,q i,..., q j. 2. la table r, où r(i, j) ( 0 i j n) est l indice k de la racine p k de l ABRO sur les nœuds p i+1,..., p j,q i,..., q j. 3. la table W, où W (i, j) =f(p i+1 )+...+ f(p j )+f(q i )+...+ f(q j ) ( 0 i j n). Le remplissage de la table C commence à la ligne 0 et se termine à la ligne n. Il est basé sur la formule suivante : 29

Fig. 4.2 ABRO d un point de vue récursif 0 si i j C(i, j) = W (i, j) + min i<k j si i<j (4.2) L idée de cette formule est de déterminer pour chaque indice k le coût de l arbre construit avec p k comme racine, un ABRO de coût C(i, k 1) comme sous-arbre gauche et un ABRO de coût C(k, j) comme sous-arbre droit ; il faut retenir celui qui minimise la quantité C(i, k 1) + C(k, j). Une fois k déterminé (si plusieurs indices donnent un coût minimal, il faut en choisir un arbitrairement), il faut stocker cet indice dans r(i, j). Il faut noter que dans le calcul de C(i, j), il faut rajouter le terme W (i, j). En effet, lorsque le sousarbre gauche de coût C(i, k 1) et le sous-arbre droit de coût C(k, j) sont rattachés à la racine p k, la profondeur de chacun des nœuds dans ces sousarbres augmente de 1. Ceci implique qu il faut rajouter dans le coût C(i, j) la fréquence de chacun de ces nœuds. Comme il faut également rajouter la fréquence de p k, cela revient finalement à rajouter W (i, j) au coût C(i, j). Il est possible d optimiser la formule 4.2 en se basant sur l inégalité suivante démontrée par Knuth dans [Knu73] : r(i, j 1) r(i, j) r(i +1,j) (4.3) 30

La formule devient alors : 0 si i j C(i, j) = W (i, j) + min (C(i, k 1) + C(k, j)) si i<j r(i,j 1) r(i,j) r(i+1,j) (4.4) La construction de l ABRO en utilisant la formule 4.4 nécessite un coût en O(n 2 ) (si n est la taille de l arbre), alors que la construction avec la formule 4.2 nécessite un coût en O(n 3 ) [Knu73]. De plus, le coût d une recherche dans un tel arbre se fait en O(H) [Knu73] (où H est l entropie). 4.4 Conclusion Dans cette section, nous avons présenté un algorithme de programmation dynamique, qui construit avec un coût en O(n 2 ) une structure qui atteint l optimalité dynamique. Cette structure est statique et elle requière la connaissance de la fréquence des nœuds. En 1979, Bitner [Bit79] a présenté et analysé les Arbres Monotones Dynamiques. Cette structure est un ABR dynamique (un ABR qui permet les insertions et les suppressions), qui essaie d approximer l ABRO. 31

Chapitre 5 Arbres binaires de recherche équilibrés Dans ce chapitre, nous allons d abord définir la notion d arbre binaire de recherche équilibré. Ensuite, nous allons illustrer ce concept par la présentation des arbres rouges-noirs. Le choix de cette structure plutôt qu une autre se justifie par le fait qu elle fait partie des plus connues et des plus efficaces de sa catégorie. 5.1 Définition Un arbre binaire de recherche équilibré est un ABR, qui maintient des informations supplémentaires dans ses nœuds, de manière à ce qu il reste équilibré. Le but de cet équilibrage est qu à tout moment, la hauteur de l arbre soit logarithmique, à un facteur constant près, en le nombre d éléments dans l arbre. Ceci permet d avoir des opérations sur la structure en temps logarithmique en le nombre d éléments dans l arbre. 5.2 Arbres rouges-noirs Dans la littérature, il existe deux manières de présenter les arbres rougesnoirs : soit de les décrire comme une implémentation des arbres 2-3-4 (une description de cette structure-ci est présentée dans l ouvrage [Sed04]), soit de les décrire comme une structure vérifiant un certain nombre de conditions, qui permettent d équilibrer l arbre. Les deux méthodes sont bien évidemment équivalentes. La première méthode est plus intéressante, car elle permet de comprendre le sens des propriétés imposées aux arbres rouges-noirs. Elle permet, de plus, de comprendre aisément les algorithmes d insertion et de 32

suppression des arbres rouges-noirs, ainsi que leur preuve de correction. La deuxième méthode permet de présenter la structure de manière plus brève. Nous utiliserons la deuxième méthode pour présenter la structure. Cette description est basée sur les ouvrages de Jean Cardinal [Car04] et de Sedgewick [Sed04]. 5.2.1 Définition Les arbres rouges-noirs ont deux types d arcs : les arcs rouges et les arcs noirs. Un seul bit par nœud x est nécessaire comme information supplémentaire. Ce bit indique si l arc pointant vers ce nœud x est rouge ou noir. Un arbre, pour répondre à la définition d arbres rouges-noirs, doit vérifier les propriétés suivantes : 1. dans un chemin de la racine à une feuille, il n y a jamais deux arcs rouges successifs 2. le nombre d arcs noirs dans un chemin de la racine à un sous-arbre vide est le même quel que soit le chemin 3. le bit de couleur de la racine est noir Ces conditions permettent d équilibrer l arbre, comme il le sera démontré plus loin dans ce chapitre, de manière à ce que les opérations sur les arbres rouges-noirs se fassent en temps logarithmique au pire cas en le nombre d éléments dans l arbre. 5.2.2 Recherche L algorithme de recherche pour les arbres rouges-noirs est identique à l algorithme d accès des ABR défini pour le modèle dynamique (cfr point 2.2.1). 5.2.3 Insertion L algorithme d insertion pour les arbres rouges-noirs est le suivant. En commençant le traitement à la racine, il faut effectuer les opérations suivantes : 1. Désignons par x le nœud courant. Si x a deux arcs sortants rouges, il faut traiter ce nœud de la manière suivante : (a) colorier les deux arcs sortants de x en noir (b) colorier l arc liant x à p (où p est le père de x) en rouge 33

(c) si l arc liant p à g (où g est le père de p ) est rouge, il faut effectuer une rotation. Cette rotation est simple (rotation entre p et g) si x et p sont tous deux des fils gauches ou s ils sont tous deux des fils droits ; elle est double sinon. Après cet éventuel traitement, il faut déplacer le pointeur courant sur le fils gauche ou le fils droit de x suivant que la clé à insérer soit, respectivement, plus petite ou plus grande que x. Cette première étape est à itérer tant que le nœud courant ne pointe pas sur un sous-arbre vide. 2. À ce niveau, le pointeur courant pointe sur un sous-arbre vide. Il ne suffit, dès lors, qu à insérer le nouveau nœud dans ce sous-arbre vide en coloriant son bit de couleur en rouge. Après cela, si l arc liant p (où p est le père du nœud inséré) à g (où g est le père de p) est rouge, il faut effectuer une rotation. Cette rotation est simple (rotation entre p et g) si le nœud inséré et p sont tous deux des fils gauches ou s ils sont tous deux des fils droits ; elle est double sinon. Les notions de rotation simple et de rotation double sont définies au point 2.1.4. Certains lecteurs pourraient être sceptiques quant à la correction de cet algorithme, mais si nous considérons les arbres rouges-noirs comme une implémentation des arbres 2-3-4, alors cette preuve peut facilement être établie. Les utilisateurs intéressés par cela peuvent consulter la référence [Car04] ou [Sed04]. 5.2.4 Successeur L opération successeur pour un nœud x donne l élément, qui suit x dans l ordre symétrique. L algorithme suivant permet de déterminer le successeur de x. Supposons que le pointeur courant pointe sur le nœud x (si ce n est pas le cas, il suffit de réaliser une recherche sur cet élément). Ensuite, deux cas sont à envisager, selon que x ait un fils droit ou non : 1. Si x a un fils droit, noté y, il faut se positionner sur le fils droit de x et suivre le chemin des fils gauches à partir de y. Le successeur de x est alors le dernier nœud rencontré sur ce chemin. 2. Si x n a pas de fils droit, il faut remonter dans l arbre, tant que x appartient au sous-arbre droit du nœud courant. Le successeur de x est, alors, le premier nœud dans cette remontée, qui contient x dans son sous-arbre gauche. S il n existe pas de tel nœud, alors x n a pas de successeur. 34

5.2.5 Prédécesseur L opération prédécesseur pour un nœud x donne l élément, qui précède x dans l ordre symétrique. L algorithme suivant permet de déterminer le prédécesseur de x. Supposons que le pointeur courant pointe sur le nœud x (si ce n est pas le cas, il suffit de réaliser une recherche sur cet élément). Ensuite, deux cas sont à envisager, selon que x ait un fils gauche ou non : 1. Si x a un fils gauche, noté y, il faut se positionner sur le fils gauche de x et suivre le chemin des fils droits à partir de y. Le prédécesseur de x est alors le dernier nœud rencontré sur ce chemin. 2. Si x n a pas de fils gauche, il faut remonter dans l arbre, tant que x appartient au sous-arbre gauche du nœud courant. Le prédécesseur de x est, alors, le premier nœud dans cette remontée, qui contient x dans son sous-arbre droit. S il n existe pas de tel nœud, alors x n a pas de prédécesseur. 5.2.6 Analyse des performances Les deux démonstrations présentées dans cette partie sont basées sur l ouvrage de Sedgewick [Sed04] Lemme 1. Soient un arbre rouge-noir et un nœud x appartenant à cet arbre. Le sous-arbre A de x contient au moins 2 bh(x) 1 nœuds (bh(x) est la hauteur noire de x, c est-à-dire le nombre de nœuds ayant un bit noir entre x (inclus) et la feuille la plus profonde de x moins 1. On impose que bh(x) 0). Démonstration : la hauteur de x : La démonstration de ce lemme se fait par récurrence sur 1. Initialisation de la récurrence : Si la hauteur de x vaut 0, alors bh(x) vaut 0. Dès lors, le sous-arbre A de x doit contenir au moins 2 bh(x) 1= 2 0 1 = 0 nœud. Or, si x a une hauteur de 0, cela signifie que le sousarbre A consiste en la seule feuille x. Le sous-arbre A contient, donc, un élément et le lemme est, alors, vérifié. 2. Pas de récurrence : Supposons que le lemme soit vrai pour une hauteur h 1 et montrons qu il l est aussi pour une hauteur h. Supposons que le nœud x ait une hauteur h et une hauteur noire bh(x). Considérons le pire cas, où x a deux enfants ; en effet, on augmente ainsi le nombre d éléments dans le sous-arbre de x. Chaque enfant de x a une hauteur noire qui vaut bh(x) ou bh(x) 1, selon que son bit de 35