Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
1
Arbres AVL Arbres AVL
2
Arbres AVL Les arbres AVL sont balancés.
Un arbre AVL est un arbre de recherche binaire T tel que pour chaque nœud interne v de T, les hauteurs des enfants de v peuvent différer au plus de 1. Exemple d’arbre AVL où la hauteur est indiquée à côté de chaque nœud.
3
Hauteur d’un arbre AVL Proposition: La hauteur d’un arbre AVL T contenant n clés est O(log n). Justification: La façon la plus simple d’aborder ce problème est de trouver n(h): le nombre minimum de nœuds internes d’un arbre AVL de hauteur h. On voit que n(1) = 1 et n(2) = 2 Pour n ≥ 3, un abre AVL de hauteur h contient le nœud racine, un sous-arbre AVL de hauteur n-1 et un autre sous-arbre AVL de hauteur n-2. i.e. n(h) = 1 + n(h-1) + n(h-2)
4
Hauteur d’un arbre AVL (suite)
Connaissant n(h-1) > n(h-2), on obtient n(h) > 2n(h-2) n(h) > 2n(h-2) n(h) > 4n(h-4) … n(h) > 2in(h-2i) On résout pour le cas de base et on obtient: n(h) ≥ 2 h/2-1 On prend les logarithmes: h < 2log n(h) +2 Ainsi, la hauteur d‘un arbre AVL est O(log n)
5
Insertion Un arbre de recherche binaire T est dit balancé si pour chaque nœud v, la hauteur des enfants de v diffère par au plus un. L’insertion d’un nœud dans un arbre consiste à effectuer un expandExternal(w) sur T, ce qui change la hauteur de certains nœuds de T. Si une insertion fait que T devient débalancé, on grimpe dans l’arbre à partir du nœud nouvellement créé jusqu’à ce qu’on trouve le premier nœud x tel que son grand-parent z est un nœud débalancé. Puisque z est devenu débalancé par une insertion dans le sous-arbre dont la racine est son enfant y, hauteur(y) = hauteur(frère(y)) + 2 Pour rebalancer...
6
Insertion: rebalancement
Pour rebalancer le sous-arbre de racine z, on doit effectuer une restructuration On renomme x, y, et z en a, b, et c selon l’ordre de la traversée des nœuds dans une traverse en-ordre. z est remplacé par b, dont les enfants sont maintenant a et c, dont les enfants, à leur tour, consistent dans les quatre autres sous-arbres qui étaient auparavant les enfants de x, y, et z.
7
Insertion (suite) Non balancé... ...balancé
8
Restructuration Les quatre façons d’effectuer la rotation des nœuds d’un arbre AVL, représentées graphiquement. -Rotations simples : a = z rotation simple b = y b = y a = z c = x c = x T T 3 T T 1 3 T T T 1 2 T 2 c = z rotation simple b = y b = y a = x c = z a = x T 3 T T T 2 T T T 1 2 3 T 1
9
Restructuration (suite)
Rotations doubles : rotation double a = z b = x c = y a = z c = y b = x T T 2 T T T T T 2 3 1 3 T 1 rotation double c = z b = x a = y a = y c = z b = x T T 3 1 T T0 T T T 1 2 3 T 2
10
L’algorithme restructure( )
Algorithme restructure(x) : Entrée: Un nœud x d’un arbre de recherche binaire T qui possède un parent y et un grand-parent z Sortie: L’arbre T restructuré par une rotation (simple ou double impliquant les nœuds x, y, et z. 1: Soit (a, b, c) une liste en-ordre des nœuds x, y, et z, et soit (T0, T1, T2, T3) une liste en-ordre des quatre sous-arbres de x, y, et z, n’ayant pas leur racine à x, y, ou z. 2. Remplacer le sous-arbre ayant sa racine à z avec un nouveau sous-arbre dont la racine est à b. 3. Soit a l’enfant gauche de b et soient T0, T1 les sous-arbres gauche et droit de a, respectivement. 4. Soit c l’enfant droit de b et soient T2, T3 les sous-arbres gauche et droit de c, respectivement.
11
Algorithm de restructuration cut/link (suite)
Voici les détails de cet algorithme... Tout arbre qui a besoin d’être rebalancé peut être découpé en 7 parties : x, y, z, et les 4 sous-arbres ancrés aux enfants de ces nœuds (T0 à T3) z
12
Algorithm de restructuration cut/link (suite)
z Faire un nouvel arbre qui est balancé et placer les 7 parties de l’ancien arbre dans le nouvel arbre de façon à ce que la numérotation soit encore correcte quand on traverse le nouvel arbre en-ordre. Ceci fonctionne quelle que soit la façon dont l’ancien arbre était débalancé. Voyons comment cela fonctionne !
13
Algorithm de restructuration cut/link (suite)
Numéroter les 7 parties en traversant l’arbre en-ordre (noter que x, y et z sont maintenant renommés selon leur ordre dans la traversée)
14
Algorithm de restructuration cut/link (suite)
Créez un tableau, numéroté 1 à 7 (on peut ignorer le 0ième élément avec une perte d’espace minime) Coupez (cut()) les 4 arbres T et placez les selon leur rang en-ordre dans le tableau.
15
Algorithm de restructuration cut/link (suite)
Effectuez cut x, y, et z dans cet ordre (enfant, parent, grand-parent) et placez les dans leur rang en-ordre dans le tableau. Ensuite on peut re-linker ces sous-arbres à l’arbre principal. Linkez d’abord le rang 4 (b) à l’endroit où se trouvait la racine du sous-arbre auparavant.
16
Algorithm de restructuration cut/link (suite)
Linkez les rangs 2 (a) et 6 (c) comme enfants de 4.
17
Algorithm de restructuration cut/link (suite)
Finalement, linkez les rangs 1, 3, 5, et 7 comme enfants de 2 et de 6. Et vous avez un arbre balancé!
18
Algorithm de restructuration cut/link (suite)
Cet algorithme de restructuration a exactement le même effet que l’un des 4 cas de rotation discutés auparavant. Avantages: pas d’analyse de cas, plus élégant Désavantage: un peu plus de code à écrire Même ordre de temps d’exécution
19
Suppression On voit facilement qu’effectuer removeAboveExternal(w) peut débalancer T. Soit z le premier nœud débalancé rencontré en remontant l’arbre à partir de w. De plus, soit y l’enfant de z ayant la plus grande hauteur, et soit x l’enfant de y ayant la plus grande hauteur. On peut effectuer l’opération restructure(x) pour rebalancer le sous-arbre de racine z. Comme cette restructuration peut débalancer un autre nœud plus haut dans l’arbre, on doit continuer à vérifier l’état de balancement jusqu’à la racine de T.
20
Suppression (suite) Exemple de suppression dans un arbre AVL:
88 44 17 78 32 50 48 62 1 4 2 3 54 T y Oh non, débalancé! x T 2 T 1 3 Ouf, rebalancé!
21
Suppression (suite) Exemple de suppression dans un arbre AVL :
Oh non, débalancé! Ouf, rebalancé!
22
Implémentation Pour implanter un arbre AVL en Java, on utilise la structure de nœud suivante : public class AVLItem extends Item { int height; AVLItem(Object k, Object e, int h) { super(k, e); height = h;} public int height () { return height;} public int setHeight(int h) { int oldHeight = height; height = h; return oldHeight;} }
23
Implémentation (suite)
public class SimpleAVLTree extends SimpleBinarySearchTree implements Dictionary { public SimpleAVLTree(Comparator c) { super(c); T = new RestructurableNodeBinaryTree();} private int height(Position p) { if (T .isExternal(p)) return 0; else return ((AVLItem) p.element()). height(); } private void setHeight(Position p) { // called only if p is internal ((AVLItem) p. element()). setHeight (1+Math.max(height(T .leftChild(p)), height(T .rightChild(p)))); }
24
Implémentation (suite)
private boolean isBalanced(Position p) { // test whether node p has balance factor // between -1 and 1 int bf = height(T.leftChild(p)) - height(T.rightChild(p)); return ((-1 <= bf) && (bf <= 1));} private Position tallerChild(Position p) { // return a child of p with height no // smaller than that of the other child if(height(T.leftChild(p)) >= height(T.rightChild(p)); return T.leftChild(p); else return T.leftChild(p);}
25
Implémentation (suite)
private void rebalance(Position zPos) { //traverse the path of T from zPos to the root; for each node encountered //recompute its height and perform a rotation if it is unbalanced while (! T.isRoot(zPos)) { zPos = T.parent(zPos); setHeight(zPos); if (!isBalanced(zPos)) { // perform a rotation Position xPos = tallerChild(tallerChild(zPos)); zPos = ((RestructurableNodeBinaryTree)T) .restructure(xPos); setHeight(T.leftChild(zPos)); setHeight(T.rightChild(zPos)); }}}
26
Implémentation (suite)
public void insertItem(Object key, Object element) throws InvalidKeyException { super.insertItem(key, element);// may throw an InvalidKeyException Position zPos = actionPos; // start at the insertion position T.replace(zPos, new AVLItem(key, element, 1)); rebalance(zPos);} public Object remove(Object key) throws InvalidKeyException { Object toReturn = super.remove(key); // may throw an InvalidKeyException if (toReturn != NO_SUCH_KEY) { Position zPos = actionPos; // start at the removal position return toReturn; }}
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.