Arbres 234 Recherche dans un (sous)arbre-2.3.4 Recherche
Transcription
Arbres 234 Recherche dans un (sous)arbre-2.3.4 Recherche
Arbres 234 15 • Arbre de recherche dont les nœuds contiennent 1, 2 ou 3 éléments triés et dont toutes les feuilles sont à la même hauteur • Un nœud contenant x1<…<xk-1 a k sousarbres tels que : 4 10 13 1 3 7 8 30 40 11 12 – les éléments du 1er sous-arbre sont ≤ x1, – tous les éléments du ième sous-arbre sont > xi-1 et ≤ xi, – tous les éléments du kième sous-arbre sont > xk-1 14 50 60 35 20 28 10 noeuds, 18 éléments 268 269 Recherche dans un (sous)arbre-2.3.4 Recherche dans un (sous)arbre-2.3.4 • Même principe que dans un (sous) arbre binaire de recherche • On compare x avec les éléments contenus dans la racine de A – si la recherche se termine sur une feuille qui ne contient pas x, alors x n’appartient pas à A – s’il existe j tel que x=xj, alors x est trouvé – si x<x1 recherche dans le premier sous-arbre de A – si xj<x<xj+1 recherche dans le (j+1) ième sousarbre de A – si x>max(xi), recherche dans le dernier sous-arbre • Recherche en O(lg n) puisque l’arbre est équilibré par construction 270 271 Insertion dans un (sous) arbre 234 Insertion dans un (sous) arbre 234 • Pour insérer x – On descend jusqu’à la feuille où x doit s’insérer (même approche que pour la recherche) – Si la feuille est pleine on commence par l’éclater…. … s1 s2 s3 …,e2, … éclatement e1,e2,e3 e1 s4 s1 • Lors d’un éclatement, l’élément du milieu remonte dans le père • Si le père est plein, on l’éclate à son tour… … e1,e2,e3 e3 s2 s3 s4 272 s1 s2 s3 …,e2, … éclatement e1 s4 s1 e3 s2 s3 s4 273 1 Exemple Insertion dans un (sous) arbre 234 Insertion avec éclatement en remontée Insertion successive de 4, 35, 10, 13, 3, 30,15,12, 7, 40, 20, 11, 6, à partir de l’arbre vide • 2 stratégies possibles – Éclatement en remontée (seulement quand il devient indispensable) – Éclatement (préventif) à la descente des nœuds pleins 4 10 35 4 4 35 4 10 35 A cette étape, A est équivalent à l’arbre binaire : 10 4 35 274 13 13 10 4 35 275 15 10 4 12 3 3 4 3 4 30 10 35 13 3 4 13 35 15 10 30 10 30 13 15 3 4 7 10 30 35 12 13 15 3 4 7 10 30 12 13 15 13 30 35 3 4 40 3 4 7 10 30 12 13 15 35 40 276 3 4 7 20 3 4 7 35 10 13 35 20 35 277 6 10 13 30 12 15 13 35 40 4 10 10 13 30 12 15 20 3 7 30 12 15 20 35 40 35 40 6 13 11 3 4 7 10 13 30 11 12 15 20 4 10 30 35 40 3 278 6 7 12 15 20 35 40 279 2 4 Insertion avec éclatement à la descente Avec la méthode précédente, éclatements en cascade possibles (éventuellement sur toute la hauteur de l’arbre si le chemin suivi n’est formé que nœuds pleins) 4 13 Pour éviter ce phénomène, on travaille sur des arbres-2.3.4 ne contenant jamais deux nœuds pleins à la suite : -> au plus un éclatement lors d’une insertion. Réalisation de cette condition par éclatement à la descente : pour insérer un élément, on parcourt un chemin dans l’arbre à partir de la racine et on fait éclater les nœuds pleins au fur et à mesure de leur rencontre. 10 35 4 35 3 10 15 10 13 35 10 30 35 13 15 3 4 13 30 35 3 4 10 3 4 13 35 4 30 4 10 35 280 12 3 4 7 10 30 12 13 15 35 3 4 7 281 11 10 30 12 13 15 13 10 35 3 4 7 40 3 4 7 15 20 11 12 35 40 10 30 12 13 15 35 40 6 13 4 10 20 10 13 30 3 4 7 30 12 15 20 3 6 7 30 11 12 35 40 15 20 35 40 282 Les transformations de rééquilibrage à la descente sont purement locales : lorsqu’un nœud éclate, son père ne peut être un nœud plein car sinon on l’aurait fait éclater avant ; il n’y a donc que 2 cas possibles, suivant que le père contient 1 ou 2 éléments Ces transformations n’augmentent pas la hauteur de l’arbre, sauf si on éclate la racine ; dans ce cas la hauteur augmente de 1 Analyse de la complexité L’insertion est également en Θ(log n ) : dans le cas d’un éclatement à la montée ou à la descente, on opère toujours sur un chemin de la racine à une feuille de l’arbre 284 283 Représentation des arbres-2.3.4 Pour représenter les différents types de nœuds ; on peut choisir une représentation « maximale » : P0 e1 P1 e2 P2 e3 P3 On peut également opter pour une implantation équivalente : les arbres binaires Rouge / Noir 285 3 Tas binaire (heap) Exemple de tas-min : • Structure de donnée pouvant être représentée par un arbre binaire vérifiant deux contraintes Exemple de tas-max : 35 1 – c'est un arbre binaire complet : tous les niveaux excepté le dernier doivent être totalement remplis – les valeurs des nœuds satisfont à une propriété de tas 2 5 • La propriété dépend du type de tas – Dans un tas max, pour tout nœud interne x, la valeur de x est supérieure aux valeurs de chacun des fils de x – Dans un tas min, pour tout nœud interne x, la valeur de x est inférieure aux valeurs de chacun des fils de x 20 17 4 8 7 15 5 13 12 6 9 6 3 2 7 • Dans un tas max (resp. min) la valeur maximale (resp. minimale) est toujours à la racine 286 • Permet d’implémenter le type abstrait file de priorité – insérer un élément – lire puis supprimer l'élément ayant la plus grande/petite valeur – tester si la file de priorité est vide ou pas • On insère x à la prochaine position libre, c-à-d la position libre la plus à gauche possible sur le dernier niveau (pour une implémentation en tableau, il s’agit de la première case vide) • On effectue si nécessaire une suite d’échanges pour rétablir la propriété de tas : tant que x n'est pas la racine de l'arbre et que x est strictement inférieur à son père on échange les positions entre x et son père. – L’élément racine est à l’indice 1 – Les fils gauche et droit de l’élément d’indice i sont situés aux indices respectifs 2i et 2i+1 – Le père de l’élément d’indice i est situé à l’indice i/2 – Complexité : • Lors de l'algorithme ci-dessus on effectue au plus h échanges, où h est la hauteur de l’arbre. Dans un arbre binaire complet, h = log2n, où n est le nombre d’éléments. Donc, le coût d’insertion est en O(log2n) . … 2 4 5 8 15 … 6 20 7 1 2 3 4 5 6 7 8 9 • Insertion d’un élément x dans un tas-min – Deux étapes : • Un tas binaire étant un arbre complet, il peut être représenté par un tableau dans lequel : 1 287 288 • Suppression de l’élément racine dans un tas-min 289 • Recherche de l’élément minimum dans un tas-min – On souhaite retirer la racine de notre tas binaire (c'est-à-dire le minimum de notre tas selon la relation d'ordre associée) – Il est toujours situé à la racine – L’accès se fait en temps constant : O(1) – Deux étapes : • On supprime la racine et on met à sa place le nœud qui était en dernière position de l'arbre binaire (donc le nœud le plus à droite sur le dernier niveau) que l'on notera x. • On effectue une suite d’échanges pour rétablir la propriété de tas : tant que x a des fils et que x est strictement supérieur à un de ses fils, on échange les positions entre x et le plus petit de ses fils. • Attention à ne pas confondre le tas binaire avec l’arbre binaire de recherche ! – Dans un tas-min, l’élément minimum est à la racine – Dans un arbre binaire de recherche, l’élément minimum est la feuille la plus à gauche (rappel : accès en O(log2 n) ) – Complexité : • Comme pour l’insertion, on effectue au plus h échanges, où h est la hauteur de l’arbre. Donc, le coût de suppression de la racine est en O(log2n) . 290 291 4 Graphe Définitions • Un graphe non orienté est un couple <S, A> où • Idée générale – Notion plus générale que la notion d’arbre – Arbre = cas particulier d’un graphe • S est un ensemble fini de sommets • A est un ensemble fini de paires de sommets, appelées arêtes • Graphe – Modélisation de relations binaires entre des éléments 2 1 4 3 292 S = { 1, 2, 3, 4 } A = { {1, 2}, {1, 3}, {1, 4}, {2, 4} } Définitions Définitions • Un graphe orienté est un couple <S, A> où • Il arrive qu’une information de coût soit associée aux arcs (ou arêtes), voire aux nœuds (resp. sommets) • Un graphe valué est un triplet <S, A, C> où – S est un ensemble fini de nœuds – A un ensemble fini de paires ordonnées de nœuds, appelées arcs 2 4 3 5 293 – S est un ensemble fini de nœuds (ou sommets), – A un ensemble fini d’arcs (ou d’arêtes) – C une fonction de A dans R appelée fonction de coût 1 S = { 1, 2, 3, 4, 5 } A = { (1, 2), (1, 3), (2, 3), (3, 2), (3, 2), (4, 4), (4, 5) } 294 295 Exemples Exemples • GPS : Localités reliées par des voies de communication (routes, voies ferrées, lignes aériennes, …), la fonction de coût pouvant correspondre à une distance, ou un temps de parcours, le prix du trajet... → Recherche de plus courts chemins • Représentation de localités reliées par des canalisations (eau, gaz, électricité) caractérisées par leur débit et leur capacité. Certains nœuds pouvant correspondre à des stations de distribution ou de pompage → Problème de flux maximal Lille Réseau Paris Brest 2 Nantes Lyon 2 Nice 3 2 3 3 6 Toulouse 4 Pipelines 8 296 297 5 Algorithmes Exemples • Explorations • Représentation – des configurations possibles d’un jeu tactique par des nœuds, – des coups légaux par des arcs permettant de passer d’une configuration à une autre →Recherche position gagnante, séquences de coups forcés, etc. – Parcours en profondeur, en largeur – Tri topologique – Composantes fortement connexes, ... • Recherche de chemins – Clôture transitive – Chemin de coût minimal – Circuits eulériens et hamiltoniens, ... • Arbres couvrants – Algorithmes de Kruskal et Prim 298 299 Terminologie Algorithmes • Etant donné un arc (x, y) – x est l’extrémité initiale de l’arc, – y l’extrémité terminale • Réseaux de transport – Flot maximal • Divers • On dit que – Coloration d'un graphe – Test de planéarité, ... 2 4 1 3 – x et y sont adjacents – y est un successeur de x – x est un prédécesseur de y • Les arcs qui partent d’un nœud lui sont incidents extérieurement, ceux qui y arrivent lui sont incidents intérieurement 300 Terminologie Terminologie • Dans un graphe orienté (resp. non orienté) G, on appelle degré d’un nœud (resp. sommet) x et on note d°(x) le nombre d’arcs (resp. d’arêtes) dont x est une extrémité • Demi-degré extérieur d’un nœud : nombre d’arcs incidents extérieurement • Demi-degré intérieur d’un nœud : nombre d’arcs incidents intérieurement 2 4 1 3 301 302 • Dans un graphe orienté (resp. non orienté) G, on appelle chemin (resp. chaîne) de longueur l une suite de l+1 nœuds (resp. sommets) (s0, …, sl) tels que ∀i,0 ≤ i ≤ l − 1, s i → s i +1 est un arc (resp. arête) de G • Un chemin (resp. une chaîne) est dit élémentaire s’il ne contient pas plusieurs fois le même nœud (resp. sommet) • Un circuit (resp. un cycle) est un chemin (resp. une chaîne) tel (resp. telle) que les 2 sommets aux extrémités coïncident 303 6 Terminologie • Un graphe orienté est dit fortement connexe si pour toute paire de noeuds distincts (u,v) il existe un chemin de u vers v et un chemin de v vers u. • Un graphe non orienté est dit connexe si pour toute paire de sommets distincts (u,v) il existe une chaîne entre u et v 2 4 1 3 Terminologie • Un arbre est un graphe non orienté, connexe et sans cycle • Etant donné un graphe orienté G = <S,A>, on appelle racine de G un nœud r de S tel que tout autre nœud puisse être atteint par un chemin d’origine r • On appelle arborescence un graphe orienté admettant une racine et tel que le graphe non orienté associé soit un arbre 304 Type Abstrait Graphe 305 Représentations possibles • Prévoir des procédures – d’initialisation, de testament, d’affectation – d’ajout / de retrait d’un nœud ou d’un arc • Prévoir des fonctions – testant l’existence d’un nœud ou d’un arc • Prévoir des routines – Permettant d’itérer • Matrices d’adjacence – Ensemble des arcs représenté par un tableau de booléens de dimension n*n, où n est le nombre de nœuds 1 1 2 1 3 4 3 4 3 4 F F F F 2 • sur l’ensemble des arcs issus d’un nœud (ième arc) • Sur l’ensemble des successeurs d’un nœud (ième successeur) 2 F V V F V F F V F V F F – De connaître l’origine (resp. l’extrémité) d’un 306 arc – Si le graphe est valué on remplace les booléen par le coût associé à l’arc (en réservant une valeur spécifique pour signifier l’absence d’arc) – Types 307 – Quelle propriété est vérifiée par la matrice d’adjacence d’un graphe non orienté? – Quel est la complexité du parcours des successeurs d’un nœud? • Graphe = tableau [1…N x 1…N] de valeurs – Utilisable si pas plus d’un arc entre 2 nœuds 308 309 7 Représentations possibles • Matrice d’adjacence • Listes d’adjacence – Avantages : • Ajout, suppression et test d’existence d’un arc en Θ(1) • Simplicité d’implantation – Inconvénients • Parcours de tous les successeurs ou de tous les prédécesseurs d’un sommet en Θ(n) • Une consultation de l’ensemble des arcs du graphe requiert un temps en Θ(n2) et cette représentation exige un espace mémoire de Θ(n2) • Représentation « figée » (réallocation nécessaire si ajout ou suppression de sommet) • On représente les nœuds et les arcs • On associe à chaque nœud la liste de ses arcs incidents extérieurement (et éventuellement, la liste de ses arcs incidents intérieurement) • On associe à chaque arc les nœuds extrémités initiale et finale 310 Représentations possibles 311 Représentations possibles • Listes d’adjacences : structures • Listes d’adjacence structure Graphe { nœuds : tableau/liste de Nœud arcs : tableau/liste d’Arc } structure Nœud { .... /* Attributs du nœud */ arcs_inc_ext : tableau/liste de pointeurs sur Arc arcs_inc_int : tableau/liste de pointeurs sur Arc } structure Arc { val : entier ou réel extremite_initiale, extremite_finale : pointeur sur Nœud } – Avantages • Cette représentation utilise un espace mémoire en Θ(n+p) pour un graphe avec n nœuds et p arcs • Accès optimisé aux successeurs et prédécesseurs d’un nœud : Θ(deg+) et Θ(deg-) • Ajout et suppression de nœud sans réallocation complète de la structure – Inconvénient • Structure plus délicate à implanter et à maintenir que la matrice d’adjacence 312 Parcours de graphe 313 313 Parcours de graphe • But : parcourir l’ensemble des nœuds du graphe, pour effectuer une certaine action en chacun des nœuds (ex. affichage d’information) • Exploration d’un graphe plus compliquée que celle d’un arbre, mais elle s’en inspire! • Il existe 2 grandes stratégies de parcours : • Lors du parcours, on matérialisera l’état d’un nœud par une couleur – Blanc : nœud non découvert – Gris : nœud découvert – Noir : nœud dont tous les successeurs ont été parcourus – le parcours en profondeur (depth-first search) – le parcours en largeur (breadth-first search) 314 315 8 Parcours en profondeur (DFS) Parcours en profondeur • On considère un graphe orienté dont tous les nœuds sont initialement non découverts (blanc) • Le parcours en profondeur consiste à – choisir un nœud de départ s et le marquer comme découvert (gris) – suivre un chemin issu de s aussi loin que possible en marquant les nœuds au fur et à mesure qu’on les découvre – en fin de chemin, revenir au dernier choix fait et prendre une autre direction. 316 procédure DFS(donnée-résultat G : Graphe) variable u : Nœud Début pour tout Nœud u de G faire u.couleur← blanc; u.père ← nil finpour temps ← 0 pour tout Nœud u de G faire si u.couleur = blanc alors u.découverte ←temps; temps ++ u.couleur← gris DFS_visite(G,u) finsi finpour fin 317 Parcours en profondeur (DFS) Procédure DFS_visite(donnée-résultat G : graphe, u : Nœud) variable v : Nœud Début pour tout Nœud v successeur de u faire si v.couleur = blanc alors v.découverte ←temps; temps ++ v.couleur← gris v.père←u DFS_visite(G, v) finsi finpour u.couleur ← noir u.fin ← temps; temps++ 318 fin • On obtient l’ordre de parcours suivant des nœuds en partant de 1 : 1, 3, 2, 6, 5, 7, 4, 9, 8 7 1 5 6 3 2 • Effectuer le parcours en profondeur sur le graphe suivant 7 1 5 6 3 2 8 4 9 319 Parcours en profondeur (DFS) • Complexité en temps : O(N+M) où N est le nombre de nœuds et M le nombre d’arcs – en effet, un nœud n’est empilé qu’une seule fois (passage de blanc à gris) et chaque arc n’est traité qu’une seule fois à partir de son extrémité initiale 8 4 • Complexité en espace : O(N) 9 – comme un nœud est empilé au plus 1 fois, la pile d’appel a une profondeur en O(N) 320 321 9 Parcours en largeur (BFS) • Pour un sommet de départ s on commence par visiter tous les successeurs de s avant de visiter les autres descendants de s • Le parcours en largeur consiste à visiter d’abord • tous les nœuds à distance 1 de s, • puis ceux à distance 2 qui n’ont pas été visités, • et ainsi de suite … • Le parcours en largeur permet donc de résoudre les problèmes de plus court chemin dans un graphe non valué Parcours en largeur (BFS) • Pour programmer l’algorithme, on utilise une structure de file: – lorsque à partir de s, on s’apprête à visiter ses successeurs non marqués, il est nécessaire de les ranger successivement dans une file – la recherche repartira ainsi de chacun des successeurs de s, à partir du premier. 322 323 Parcours en largeur (BFS) procédure BFS(donnée-résultat G: graphe, s : noeud) variables u,v : nœud ; F : file début pour tout noeud u ≠ s faire u.couleur←blanc; u.père ← nil; u.dist ← ∞ finpour s.couleur ← gris; s. père ← nil; s.dist ← 0; initialise_file_vide(F); enfile(F,s) tant que non est-vide(F) faire u ← tête(F); pour tout noeud v successeur de u faire si v.couleur=blanc alors v.couleur ← gris; v.père ← u; v.dist ← u.dist +1; enfile(F,v) finsi finpour défile(F); u.couleur ← noir fintantque fin • Effectuer le parcours en largeur sur le graphe suivant 1 5 6 3 2 1 5 6 3 2 8 4 9 324 325 • Complexité en temps : O(N+M) où N est le nombre de nœuds et M le nombre d’arcs • Les sommets sont visités dans l’ordre 1, 3, 5, 6, 7, 2, 8, 4, 9 7 7 – en effet, un sommet n’est mis dans la file qu’une seule fois (passage de blanc à gris) et les arêtes sont toutes parcourues 1 fois (découverte des voisins) 8 4 • Complexité en espace : O(N) la file a une longueur au plus en O(N) (si s est connecté à tous les autres sommets) 9 326 327 10 • En fait, parcours en largeur et en profondeur s’inscrivent dans une même stratégie générale d’exploration des nœuds du graphe • Ils diffèrent suivant que les successeurs d’un nœud seront rangés dans une pile ou une file 328 11