/// <summary> /// Constructor con parámetros incluidos /// </summary> /// <param name="dato">El dato a insertar</param> /// <param name="hijoIzquierdo">Si posee hijo izquierdo lo agregamos de una vez</param> /// <param name="hijoDerecho">Si posee hijo derecho lo agregamos de un vez</param> public ArbolBinarioBase(T dato, IArbolBinario <T> hijoIzquierdo, IArbolBinario <T> hijoDerecho) { this.valor = dato; this.izquierdo = hijoIzquierdo; this.derecho = hijoDerecho; this.Padre = null; this.FactorBalance = 0; }
public ArbolBinario(T dato, IArbolBinario <T> hijoIzquierdo, IArbolBinario <T> hijoDerecho) { this.Dato = dato; this.HijoIzquierdo = hijoIzquierdo; this.HijoDerecho = hijoDerecho; this.Padre = null; this.FactorBalance = 0; }
/// <summary> /// Rotación simple a derecha, se usa cuando el FE de un arbol es -2 /// </summary> /// <param name="nodo">El nodo padre que presenta el des-equilibrio</param> internal void RSD(IArbolBinario <T> nodo) { //Punteros necesarios para realizar la rotación. IArbolBinario <T> Padre = nodo.Padre; //Parde el árbol desequilibrado. IArbolBinario <T> P = nodo; //Nodo desequilibrado IArbolBinario <T> Q = P.izquierdo; IArbolBinario <T> B = Q.derecho; //Nodo con altura igual al hijo derecho de P //Si el padre del nodo desequilibrado no es null verifico si el nodo desequilibrado es el derecho //o el izquierdo, si el padre es null, significa que es la raiz. if (Padre != null) { if (Padre.derecho == P) { Padre.derecho = Q; } else { Padre.izquierdo = Q; } } else { _raiz = Q as ArbolBinarioBase <T>; _raiz.Padre = null; //para que siga funcionando el padre de la raiz debe ser nulo. } //Reconstruyo el arbol P.izquierdo = B; Q.derecho = P; //Actualizando los nuevos padres P.Padre = Q; if (B != null) { B.Padre = P; } Q.Padre = Padre; //Ajuste de valores del factor de balance if (Q.FactorBalance == 0) { P.FactorBalance = -1; Q.FactorBalance = 1; } else { P.FactorBalance = 0; Q.FactorBalance = 0; } }
internal void RDI(IArbolBinario <T> nodo) { //Punteros necesarios para realizar la rotación IArbolBinario <T> Padre = nodo.Padre; IArbolBinario <T> P = nodo; IArbolBinario <T> Q = nodo.HijoDerecho; IArbolBinario <T> R = Q.HijoIzquierdo; IArbolBinario <T> B = R.HijoIzquierdo; IArbolBinario <T> C = R.HijoDerecho; //Si el padre del nodo desequilibrado no es null verifico si el nodo desequilibrado es el derecho //o el izquierdo, si el padre es null, significa que es la raiz. if (Padre != null) { if (Padre.HijoDerecho == P) { Padre.HijoDerecho = R; } else { Padre.HijoIzquierdo = R; } } else { _raiz = R as ArbolBinario <T>; _raiz.Padre = null; //para que siga funcionando el padre de la raiz debe ser nulo. } // Recontrucción del árbol P.HijoDerecho = B; Q.HijoIzquierdo = C; R.HijoIzquierdo = P; R.HijoDerecho = Q; //Actualizando a los padres R.Padre = Padre; P.Padre = Q.Padre = R; if (B != null) { B.Padre = P; } if (C != null) { C.Padre = Q; } // Ajustar valores de Factores de Balance switch (R.FactorBalance) { case -1: { P.FactorBalance = 0; Q.FactorBalance = 1; } break; case 0: { P.FactorBalance = 0; Q.FactorBalance = 0; } break; case 1: { P.FactorBalance = -1; Q.FactorBalance = 0; } break; } R.FactorBalance = 0; }
internal void Equilibrar(IArbolBinario <T> nodo, bool esIzquierdo, bool esNuevo) { bool salir = false; //al terminar de recorrer una rama si no es necesario rotar entonces se convierte en verdadero. // Recorrer camino inverso actualizando valores de FE: while ((nodo != null) && !salir) { bool hizoRotacion = false; //Al inicio digo que no se rotó if (esNuevo) { if (esIzquierdo) { nodo.FactorBalance--; // Estamos añidiendo } else { nodo.FactorBalance++; } } else { if (nodo.FactorBalance == 0) { salir = true; } if (esIzquierdo) { nodo.FactorBalance++; // Borrando un nodo } else { nodo.FactorBalance--; } } if (nodo.FactorBalance == 0) { salir = true; // La altura de el arbol que empieza en nodo no ha variado, salir de Equilibrar } //Si existe algún desbalance en esta porción de código se realizan las rotaciones else if (nodo.FactorBalance == -2) { // Rotación a la derecha doble o simple según sea el caso y salir. if (nodo.HijoIzquierdo.FactorBalance == 1) { RDD(nodo); // Rotación doble hizoRotacion = true; } else { RSD(nodo); // Rotación simple hizoRotacion = true; } salir = true; } else if (nodo.FactorBalance == 2) { // Rotar a la izquierda doble o simple según sea el caso y salir. if (nodo.HijoDerecho.FactorBalance == -1) { RDI(nodo); // Rotación doble hizoRotacion = true; } else { RSI(nodo); // Rotación simple hizoRotacion = true; } salir = true; } if ((hizoRotacion) && (nodo.Padre != null) && (!esNuevo)) { nodo = nodo.Padre; } if (nodo.Padre != null) { if (nodo.Padre.HijoDerecho == nodo) { esIzquierdo = false; } else { esIzquierdo = true; } if ((!esNuevo) && (nodo.FactorBalance == 0)) { salir = false; } } nodo = nodo.Padre; // Calcular Factor de balance, siguiente nodo del camino ossea el padre. } }
internal void VisitarArbol(IArbolBinario <T> arbol) { miLista.Agregar(arbol.Dato); }
/// <summary> /// Rotación doble a la izquierda, se usa cuando la FE del nodo que recibe como parámetro es -2 /// (Eso significa que su arbol izquierdo es mas grande que el derecho) y /// la raiz del subarbol iquierdo tenga FE 1 /// </summary> /// <param name="nodo">El nodo con el desbalance</param> internal void RDD(IArbolBinario <T> nodo) { //Punteros necesarios para realizar la rotación IArbolBinario <T> Padre = nodo.Padre; IArbolBinario <T> P = nodo; IArbolBinario <T> Q = P.izquierdo; IArbolBinario <T> R = Q.derecho; IArbolBinario <T> B = R.izquierdo; IArbolBinario <T> C = R.derecho; //Si el padre del nodo desequilibrado no es null verifico si el nodo desequilibrado es el derecho //o el izquierdo, si el padre es null, significa que es la raiz. if (Padre != null) { if (Padre.derecho == P) { Padre.derecho = R; } else { Padre.izquierdo = R; } } else { _raiz = R as ArbolBinarioBase <T>; _raiz.Padre = null; //para que siga funcionando el padre de la raiz debe ser nulo. } // Reconstruir árbol: Q.derecho = B; P.izquierdo = C; R.izquierdo = Q; R.derecho = P; // Reasignar padres: R.Padre = Padre; P.Padre = Q.Padre = R; if (B != null) { B.Padre = Q; } if (C != null) { C.Padre = P; } // Ajustar valores de FE: switch (R.FactorBalance) { case -1: { Q.FactorBalance = 0; P.FactorBalance = 1; } break; case 0: { Q.FactorBalance = 0; P.FactorBalance = 0; } break; case 1: { Q.FactorBalance = -1; P.FactorBalance = 0; } break; } R.FactorBalance = 0; }