/// <summary> /// Implementación recursiva que agrega un elemento en un árbol AVL /// </summary> /// <param name="root">Nodo del subárbol a considerar</param> /// <param name="item">Elemento a agregar</param> /// <param name="flag">Indica si cambió la altura</param> /// <returns>Nodo del subárbol considerado</returns> protected virtual AVLNode <E> AddAVL(AVLNode <E> root, E item, ref bool flag) { AVLNode <E> n1; // Si el árbol está vacio, simplement se agrega // y se indica que cambió la altura if (root == null) { root = new AVLNode <E>(item); flag = true; } else { // El valor del elemento a agregar es menor // que el valor de la raíz del subárbol a considerar if (item.CompareTo(root.Item) < 0) { // Se agrega recursivamente por la izquierda root.Left = AddAVL(root.Left, item, ref flag); if (flag) // si cambió la altura ? { switch (root.Balance) { case -1: // antes izquierda < derecha, después se equilibra // y cambia la bandera root.Balance = 0; flag = false; break; case 0: // antes izquierda = derecha, después izquierda mas grande // en algún nivel superior puede hacer falta un rebalanceo // la bandera queda como estaba (true) root.Balance = 1; break; case 1: // antes izquierda > derecha, hay que rebalancear n1 = root.Left; if (n1.Balance == 1) { // la izquierda de la izquierda es mayor // rotación simple izquierda-izquierda root = LeftLeftRotation(root, n1); } else { // rotación doble izquierda-derecha root = LeftRightRotation(root, n1); } // subárbol ajustado cambia la bandera flag = false; break; } } } else { // El valor del elemento a agregar es mayor // que el valor de la raíz del subárbol a considerar if (item.CompareTo(root.Item) > 0) { // Se agrega recursivamente por la derecha root.Right = AddAVL(root.Right, item, ref flag); if (flag) // si cambió la altura ? { switch (root.Balance) { case -1: // antes izquierda < derecha, hay que rebalancer n1 = root.Right; if (n1.Balance == -1) { // la derecha de la derecha es mayor // rotación simple derecha-derecha root = RightRightRotation(root, n1); } else { // rotación doble derecha-izquierda root = RightLeftRoation(root, n1); } // subárbol ajustado cambia la bandera flag = false; break; case 0: // antes izquierda = derecha, después la derecha mas grande // en algún nivel superior puede hacer falta un rebalanceo // la bandera queda como estaba (true) root.Balance = -1; break; case 1: // antes izquierda > derecha, despues se equilibra // y cambia la bandera root.Balance = 0; flag = false; break; } } } else { // No se puede almacenar claves repetidas throw new Exception("Claves repetidas"); } } } return(root); }
/// <summary> /// Implementación recursiva que extraer un elemento del árbol AVL /// </summary> /// <param name="root">Nodo del subárbol a considerar</param> /// <param name="item">Elemento a extraer</param> /// <param name="flag">Indica que cambió la altura</param> /// <returns>Nodo raiz del subárbol considerado</returns> protected virtual AVLNode <E> RemoveAVL(AVLNode <E> root, E item, ref bool flag) { // No se puede extraer nodos de un árbol vacío if (root == null) { throw new Exception("No existe"); } // El valor del elemento a extraer es menor // que el valor de la raíz del subárbol a considerar if (item.CompareTo(root.Item) < 0) { // Se procesa recursivamente por la izquierda root.Left = RemoveAVL(root.Left, item, ref flag); if (flag) { // Cambió la altura, analizar el balance root = LeftBalance(root, ref flag); } } else { // El valor del elemento a extraer es mayor // que el valor de la raíz del subárbol a considerar if (item.CompareTo(root.Item) > 0) { // Se procesa recursivamente por la derecha root.Right = RemoveAVL(root.Right, item, ref flag); if (flag) { // Cambió la altura, analizar el balance root = RightBalance(root, ref flag); } } else { // encontrado AVLNode <E> q; q = root; if (q.Left == null) { // Un único descendiente, cambia la altura root = q.Right; flag = true; } else { if (q.Right == null) { // Un único descendiente, cambia la altura root = q.Left; flag = true; } else { // tiene dos subárboles !!! root.Left = Repleace(root, root.Left, ref flag); if (flag) { // Cambió la altura, analizar el balance root = LeftBalance(root, ref flag); } q = null; } } } } return(root); }
/// <summary> /// Constructor especializado, permite fijar el elemento del nodo /// y el valor de los enlaces a subárboles izquierdo y derecho /// </summary> /// <param name="item">Elemento en el nodo</param> /// <param name="next">Enlace al subárbol izquierdo</param> /// <param name="prev">Enlace al subárbol derecho</param> public AVLNode(E item = default(E), AVLNode <E> left = null, AVLNode <E> right = null) { this.Item = item; this.Left = left; this.Right = right; }