/* BUSCA EL NODO QUE CONTIENE EL 'ID' DESEADO Y VERIFICA SI SE ENCUENTRA EN UNA PÁGINA QUE CUMPLE CON SER UN NODO HOJA * DEL ÁRBOL, SI ES ASÍ SÓLO LO REMUEVE DE DICHA HOJA, SI NO DEBE ELIMINAR EL NODO DESEADO Y SUSTITUIR POR EL NODO SU_ * CESOR, POR ÚLTIMO VERIFICA QUE LA PÁGINA SIGA CUMPLIENDO CON LAS RESTRICCIONES POR HOJA Y SI NO ES ASÍ, SE DEBE RES_ * TAURAR EL SUBARBOL QUE TIENE EN LA PÁGINA 'Actual'. */ private void Remover(ref Pagina Actual, int Indice) { for (int j = Indice + 1; j <= Actual.Cuenta; j++) { Actual.Nodos[j - 1] = Actual.Nodos[j]; Actual.Ramas[j - 1] = Actual.Ramas[j]; } Actual.Cuenta--; }
/* QUITA EL NODO EN LA POSICIÓN 'Indice' Y REALIZA UN CORRIMIENTO DE DATOS. */ private void PorSucesor(ref Pagina Actual, int Indice) { Pagina Auxiliar = Actual.Ramas[Indice]; while (Auxiliar.Ramas[0] != null) { Auxiliar = Auxiliar.Ramas[0]; } Actual.Nodos[Indice] = Auxiliar.Nodos[1]; }
public void escribe_pagina(Pagina actual) { int k; Console.Write("Nodo: "); for (k = 0; k <= actual.cuenta; k++) { Console.WriteLine(actual.claves[k]); } }
public void quitar(Pagina actual, int k) { int j; for (j = k + 1; j <= actual.cuenta; j++) { actual.claves[j - 1] = actual.claves[j]; //practicamente borramos la clave con el corrimeinto actual.ramas[j - 1] = actual.ramas[j]; } actual.cuenta--; }
public void sucesor(Pagina actual, int k) { Pagina q = null; q = actual.ramas[k]; while (q.ramas[0] != null) { q = q.ramas[0]; } /* q referencia al nodo hoja*/ actual.claves[k] = q.claves[1]; }
/* DIVIDE LA PÁGINA 'Actual' EN TRES PARTES: A LA IZQUIERDA ESTARÁ LA PÁGINA QUE SE TENÍA ANTES, PERO SIN EL DATO QUE SE * DEBE SUBIR DE NIVEL; EL NODO 'Mediana' SE CONVERTIRÁ LA RAIZ, PUES ES EL VALOR MEDIO, EL QUE SE DEBE SUBIR DE NIVEL; * POR ÚLTIMO, A LA DERECHA SE TENDRÁ UNA PÁGINA 'Nueva' QUE CONTENDRÁ LOS DATOS QUE SE TENÍAN ANTES "A LA DERECHA DEL * VALOR MEDIO" EN LA PÁGINA QUE SE DIVIDIÓ. */ private void InsertarEnHoja(ref Pagina Actual, Nodo Nuevo, Pagina Auxiliar, int Indice) { int PosicionActual; for (PosicionActual = Actual.Cuenta; PosicionActual >= Indice + 1; PosicionActual--) { Actual.Nodos[PosicionActual + 1] = Actual.Nodos[PosicionActual]; Actual.Ramas[PosicionActual + 1] = Actual.Ramas[PosicionActual]; } Actual.Nodos[Indice + 1] = Nuevo; Actual.Ramas[PosicionActual + 1] = Auxiliar; Actual.Cuenta++; }
public void meterHoja(Pagina actual, int valor, Pagina rd, int k) { int i; /* desplza a la derecha los elementos para hcer un hueco*/ for (i = actual.cuenta; i >= k + 1; i--) { actual.claves[i + 1] = actual.claves[i]; actual.ramas[i + 1] = actual.ramas[i]; } actual.claves[k + 1] = valor; actual.ramas[k + 1] = rd; actual.cuenta++; }
public void generar_grafo_arbolB(Pagina raiz) { String acum = "digraph G\n" + "{\n node [shape = record,height=.1];\n"; if (raiz != null) { String acumEnlace = ""; int contNodo = 0; int contAux = 0; Queue <Pagina> cola = new Queue <Pagina>(); cola.Enqueue(raiz); while (cola.Count != 0) { Pagina tmp = cola.Peek(); cola.Dequeue(); imprimir(tmp, ref acum, ref contNodo, ref contAux, ref acumEnlace); for (int i = 0; i <= tmp.cuenta; ++i) { if (tmp.ramas[i] != null) { cola.Enqueue(tmp.ramas[i]); } } contNodo++; } acum += "\n" + acumEnlace; } acum += "}\n"; StreamWriter sw = new StreamWriter("arbolB.dot"); sw.WriteLine(acum); sw.Close(); Process a = new Process(); a.StartInfo.FileName = "\"C:\\Program Files (x86)\\Graphviz2.38\\bin\\dot.exe\""; a.StartInfo.Arguments = "-Tjpg arbolB.dot -o arbolB.png"; a.StartInfo.UseShellExecute = false; a.Start(); a.WaitForExit(); }
/* ENLISTA LAS PÁGINAS PARA LUEGO PODER ENLAZARLAS. EN CADA PÁGINA SE METEN LOS DATOS DE SUS NODOS. */ private String Enlazar(Pagina Actual, String Grafo) { if (Actual == null || Actual.isEmpty()) { return(Grafo); } foreach (Pagina Auxiliar in Actual.Ramas) { Grafo = Enlazar(Auxiliar, Grafo); if (Auxiliar != null) { Grafo += "N" + Actual.Nodos[1].ID + " -> N" + Auxiliar.Nodos[1].ID; } } return(Grafo); }
/* VERIFICA SI LA PÁGINA 'Actual', DEL LADO IZQUIERDO O DERECHO POSEE HIJOS APARTE DE LA RAMA QUE AHORA SE ENCUENTRA * DESEQUILIBRADA, SI ES ASÍ, REALIZA UN MOVIMIENTO EN UNA DIRECCIÓN QUE DEPENDERÁ DE DONDE ESTÉN SU(S) HERMANO(S): * SI POSEE ALGÚN HERMANO DEL LADO IZQUIERDO, REALIZARÁ UN MOVIMIENTO HACIA LA DERECHA * Y SI SÓLO TIENE HERMANOS A LA DERECHA, REALIZARÁ UN MOVIMIENTO A LA IZQUIERDA. * EN AMBOS CASOS SI NO SE CUMPLE QUE LA CANTIDAD DE NODOS EN LA PÁGINA SEA MAYOR A M/2, SE MANDA A COMBINAR LAS PÁ_ * GINAS MANDÁNDOLE EL ÍNDICE. */ private void MovimientoDerecha(ref Pagina Actual, int Indice) { Pagina Problema = Actual.Ramas[Indice]; Pagina Izquierda = Actual.Ramas[Indice - 1]; for (int j = Problema.Cuenta; j >= 1; j--) { Problema.Nodos[j + 1] = Problema.Nodos[j]; Problema.Ramas[j + 1] = Problema.Ramas[j]; } Problema.Cuenta++; Problema.Ramas[1] = Problema.Ramas[0]; Problema.Nodos[1] = Actual.Nodos[Indice]; Actual.Nodos[Indice] = Izquierda.Nodos[Izquierda.Cuenta]; Problema.Ramas[0] = Izquierda.Ramas[Izquierda.Cuenta]; Izquierda.Cuenta--; }
public void insertar(ref Pagina raiz, int valor) { bool suber_arriba = false; int mediana = 0; Pagina p, nd = null; Empujar(raiz, valor, ref suber_arriba, ref mediana, ref nd); if (suber_arriba) //si se produjo una reorganizacion de nodos lo cual ser dividio la raiz entonces, la bandera sube_arriba lo indica { p = new Pagina(orden); p.cuenta = 1; p.claves[1] = mediana; p.ramas[0] = raiz; p.ramas[1] = nd; raiz = p; } }
/* ESTABLECE LA PÁGINA 'Problema' Y SU HERMANO 'Izquierda', PROCEDE A MOVER A LOS NODOS DE LA PÁGINA 'Problema' PARA DE_ * JAR UN ESPACIO PARA METER EL ÚLTIMO NODO DE SU HERMANO 'Izquierda'. */ private void MovimientoIzquierda(ref Pagina Actual, int Indice) { Pagina Problema = Actual.Ramas[Indice - 1]; Pagina Derecha = Actual.Ramas[Indice]; Problema.Cuenta++; Problema.Nodos[Problema.Cuenta] = Actual.Nodos[Indice]; Problema.Ramas[Problema.Cuenta] = Derecha.Ramas[0]; Actual.Nodos[Indice] = Derecha.Nodos[1]; Derecha.Ramas[1] = Derecha.Ramas[0]; Derecha.Cuenta--; for (int j = 1; j <= Derecha.Cuenta; j++) { Derecha.Nodos[j] = Derecha.Nodos[j + 1]; Derecha.Ramas[j] = Derecha.Ramas[j + 1]; } }
/* REALIZA BÚSQUEDA POR ALTURA, UTILIZANDO LA BÚSQUEDA POR NIVELES PARA VERIFICAR SI EXISTE O NO EN UNA PÁGINA, RETORNAN_ * DO LA PÁGINA SI FUE ENCONTRADA Y 'null' SI NO. */ public void Insertar(ref Pagina Raiz, Nodo Nuevo) { Boolean HayQueSubir = false; Nodo Mediana = new Nodo(random); Pagina Nueva = new Pagina(); Empujar(ref Raiz, Nuevo, ref HayQueSubir, ref Mediana, ref Nueva); if (HayQueSubir) { Pagina Auxiliar = new Pagina(); Auxiliar.Cuenta = 1; Auxiliar.Nodos[1] = Mediana; Auxiliar.Ramas[0] = Raiz; Auxiliar.Ramas[1] = Nueva; Raiz = Auxiliar; } }
/* INSERTA EL NODO 'Nuevo' EN LA PÁGINA 'Actual', CUANDO ESTA SE ENCUENTRA EN EL ÚLTIMO NIVEL DEL ÁRBOL. */ public void Eliminar(ref Pagina Raiz, String ID) { Boolean Encontrado = false; EliminarNodo(ref Raiz, ID, ref Encontrado); if (Encontrado) { Console.Write("Dato " + ID + " fue eliminada."); if (Raiz.Cuenta == 0) { Raiz = Raiz.Ramas[0]; } } else { Console.Write("No existe en el árbol."); } }
/* REALIZA BÚSQUEDA POR NIVELES, RECORRIENDO LA PÁGINA 'Actual' RETORNANDO SI FUE ENCONTRADA O NO. */ public Pagina Buscar(ref Pagina Actual, String ID, ref int Indice) { if (Actual == null) { return(Actual); } else { Boolean Esta = BuscarNodo(ref Actual, ID, ref Indice); if (Esta) { return(Actual); } else { return(Buscar(ref Actual.Ramas[Indice], ID, ref Indice)); } } }
private Boolean BuscarNodo(ref Pagina Actual, String ID, ref int Indice) { Boolean Encontrado = false; if (String.Compare(ID, Actual.Nodos[1].ID) < 0) { Indice = 0; } else { Indice = Actual.Cuenta; while (String.Compare(ID, Actual.Nodos[Indice].ID) < 0 && Indice > 1) { Indice--; } Encontrado = String.Equals(ID, Actual.Nodos[Indice].ID, StringComparison.Ordinal); } return(Encontrado); }
public void eliminar(ref Pagina raiz, int valor) { bool encontrado = false; eliminarRegistro(raiz, valor, ref encontrado); if (encontrado) { Console.WriteLine("INFO: clave eliminada: " + valor.ToString()); if (raiz.cuenta == 0) { /* la raiz esta vacia, se libera el nodo y se establece la nueva raiz*/ Pagina p = raiz; raiz = raiz.ramas[0]; } } else { Console.WriteLine("INFO: la clave " + valor.ToString() + "no se encuentra"); } }
public void moverDerecha(Pagina actual, int k) { int j = 0; Pagina nodoProblema = actual.ramas[k]; Pagina nodoIzquierdo = actual.ramas[k - 1]; for (j = nodoProblema.cuenta; j >= 1; j--) { nodoProblema.claves[j + 1] = nodoProblema.claves[j]; nodoProblema.ramas[j + 1] = nodoProblema.ramas[j]; } nodoProblema.cuenta++; nodoProblema.ramas[1] = nodoProblema.ramas[0]; /* baaja la clave del nodo padre*/ nodoProblema.claves[1] = actual.claves[k]; /* sube a clave desde el hermano izquierdo al nodo padre, para reemplazar la que antes bajo*/ actual.claves[k] = nodoIzquierdo.claves[nodoIzquierdo.cuenta]; nodoProblema.ramas[0] = nodoIzquierdo.ramas[nodoIzquierdo.cuenta]; nodoIzquierdo.cuenta--; }
public bool buscarPagina(Pagina actual, int valor, ref int k) //k determina la rama o camino { /*tomar en cuenta que k es la direccion de las ramas por las que puede bajar la busqueda*/ bool encontrado; if (valor < actual.claves[1]) //ese 1 significa que busca desde la primera posicion en claves por tanto si cumple el valor se va a los valores menores { k = 0; //nos indica que bajaresmo por la rama 0 encontrado = false; } else //examina las claves del nodo en orden descendente { k = actual.cuenta; //desde la clave actual while ((valor < actual.claves[k]) && (k > 1)) //buscar una posicion hasta donde valor deje de ser menor ( por si vienen un valor menor a los que hay en el nodo ) { k--; } encontrado = valor == actual.claves[k]; //si la posicion encontrada es igual al valor ; lo cual clave repetida } return(encontrado); }
public void eliminarRegistro(Pagina actual, int valor, ref bool encontrado) { int k = 0; if (actual != null) { encontrado = buscarPagina(actual, valor, ref k); if (encontrado) { if (actual.ramas[k - 1] == null) //pregunto si es hoja { quitar(actual, k); } else //sino se hace la sustitucion entre la clave en la hoja y el predecesor osea el padre { sucesor(actual, k); eliminarRegistro(actual.ramas[k], actual.claves[k], ref encontrado); } } else { eliminarRegistro(actual.ramas[k], valor, ref encontrado); } /*las llamadas recursivas devuelven control a este punto * Se comprueba el numero de claves del nodo descendiente, * desde el nodo actual en la ruta de busqueda seguida*/ if (actual.ramas[k] != null) { if (actual.ramas[k].cuenta < orden / 2) //compruba que cumpla con la estructura de un arbol b; en este caso el minimos de claves por pagina { restablecer(actual, k); //el objetivo de este metodo es restablecer } } } else { encontrado = false; } }
/* CREA EL ARCHIVO '*.dot' ESCRIBIENDO EN EL LA LISTA DE NODOS Y LUEGO LOS ENLACES QUE TIENEN. */ private String Enlistar(Pagina Actual, String Grafo) { if (Actual == null || Actual.isEmpty()) { return(Grafo); } int Contador; Grafo += "N" + Actual.Nodos[1].ID + " [label=<\n"; Grafo += " <TABLE ALIGN = \"LEFT\">\n"; Grafo += " <TR>\n"; for (Contador = 1; Contador < 5; Contador++) { if (Contador <= Actual.Cuenta) { Grafo += " <TD>" + "ID = \"" + Actual.Nodos[Contador].ID + "\"<BR></BR>" + "IDActivo = \"" + Actual.Nodos[Contador].Activo + "\"<BR></BR>" + "Usuario = \"" + Actual.Nodos[Contador].Usuario + "\"<BR></BR>" + "Empresa = \"" + Actual.Nodos[Contador].Empresa + "\"<BR></BR>" + "Departamento = \"" + Actual.Nodos[Contador].Departamento + "\"<BR></BR>" + "Fecha = \"" + Actual.Nodos[Contador].Fecha + "\"<BR></BR>" + "Tiempo = \"" + Actual.Nodos[Contador].Tiempo + "\"" + " </TD>\n"; } else { Grafo += " <TD>" + " </TD>\n"; } } Grafo += " </TR>\n"; Grafo += " </TABLE>\n"; Grafo += ">, ];\n\t"; foreach (Pagina Auxiliar in Actual.Ramas) { Grafo = Enlistar(Auxiliar, Grafo); } return(Grafo); }
public void moverIzquierda(Pagina actual, int k) { int j = 0; Pagina nodoProblema = actual.ramas[k - 1]; Pagina nodoDerecho = actual.ramas[k]; nodoProblema.cuenta++; nodoProblema.claves[nodoProblema.cuenta] = actual.claves[k]; nodoProblema.ramas[nodoProblema.cuenta] = nodoDerecho.ramas[0]; /* sube la clave desde le hermano derecho al nodo padre * para reemplazar la que antes bajo*/ actual.claves[k] = nodoDerecho.claves[1]; nodoDerecho.ramas[0] = nodoDerecho.ramas[1]; //se modifico esta parte ya que no hace bien el balanceo; especificamente los indices nodoDerecho.cuenta--; for (j = 1; j < nodoDerecho.cuenta; j++) { nodoDerecho.claves[j] = nodoDerecho.claves[j + 1]; nodoDerecho.ramas[j] = nodoDerecho.ramas[j + 1]; } }
/* ESTABLECE LA PÁGINA 'Problema' Y SU HERMANO 'Derecha', PROCEDE A MOVER A LOS NODOS DE LA PÁGINA 'Problema' PARA DE_ * JAR UN ESPACIO PARA METER EL ÚLTIMO NODO DE SU HERMANO 'Derecha'. */ private void Combinar(Pagina Padre, int Indice) { int j; Pagina Izquierdo, Auxiliar; Auxiliar = Padre.Ramas[Indice]; Izquierdo = Padre.Ramas[Indice - 1]; Izquierdo.Cuenta++; Izquierdo.Nodos[Izquierdo.Cuenta] = Padre.Nodos[Indice]; Izquierdo.Ramas[Izquierdo.Cuenta] = Auxiliar.Ramas[0]; for (j = 1; j <= Auxiliar.Cuenta; j++) { Izquierdo.Cuenta++; Izquierdo.Nodos[Izquierdo.Cuenta] = Auxiliar.Nodos[j]; Izquierdo.Ramas[Izquierdo.Cuenta] = Auxiliar.Ramas[j]; } for (j = Indice; j <= Padre.Cuenta - 1; j++) { Padre.Nodos[j] = Padre.Nodos[j + 1]; Padre.Ramas[j] = Padre.Ramas[j + 1]; } Padre.Cuenta--; }
/* VERIFICA SI HAY QUE SUBIR UN NIVEL UN NODO, UTILIZANDO EL MÉTODO 'Empujar', Y LO HACE SI ES EL CASO. */ private void Empujar(ref Pagina Actual, Nodo Nuevo, ref Boolean HayQueSubir, ref Nodo Mediana, ref Pagina Nueva) { int Indice = 0; if (Actual == null || Actual.isEmpty()) { HayQueSubir = true; Mediana = Nuevo; Actual = null; Nueva = null; } else { Boolean Esta = BuscarNodo(ref Actual, Nuevo.ID, ref Indice); if (Esta) { Console.WriteLine("Dato duplicado."); HayQueSubir = false; Actual = null; return; } Empujar(ref Actual.Ramas[Indice], Nuevo, ref HayQueSubir, ref Mediana, ref Nueva); if (HayQueSubir) { if (Actual.isFull()) { Pagina Auxiliar = new Pagina(); DividirNodo(ref Actual, Mediana, ref Nueva, Indice, ref Mediana, ref Auxiliar); } else { HayQueSubir = false; InsertarEnHoja(ref Actual, Mediana, Nueva, Indice); } } } }
public void Empujar(Pagina actual, int valor, ref bool sube_arriba, ref int mediana, ref Pagina nuevo) { int k = 0; //que rama irse if (actual == null) { sube_arriba = true; mediana = valor; nuevo = null; } else { bool esta; esta = buscarPagina(actual, valor, ref k); //k busca la rama por eso se pasa por referencia if (esta) { System.Console.WriteLine("Clave Duplicada: " + valor); sube_arriba = false; return; } Empujar(actual.ramas[k], valor, ref sube_arriba, ref mediana, ref nuevo); /* devuelve control vuelve por el camino de busqueda*/ if (sube_arriba) { if (actual.pagina_llena(actual)) { dividirNodo(actual, mediana, nuevo, k, ref mediana, ref nuevo); } else { sube_arriba = false; meterHoja(actual, mediana, nuevo, k); } } } }
public bool pagina_semi_llena(Pagina actual) { return(actual.cuenta < m / 2); }
public bool pagina_llena(Pagina actual) { return(actual.cuenta == m - 1); }
public Arbol(Random random) { this.random = random; Raiz = new Pagina(); }
public void dividirNodo(Pagina actual, int valor, Pagina rd, int k, ref int mediana, ref Pagina nuevo) { int i, posMdna; posMdna = (k <= orden / 2) ? orden / 2 : orden / 2 + 1; nuevo = new Pagina(orden); //se crea una nueva pagina for (i = posMdna + 1; i < orden; i++) { /* es desplzada la mida derecha al nuevo nodo, la clave mediana se queda en el nodo origen*/ nuevo.claves[i - posMdna] = actual.claves[i]; nuevo.ramas[i - posMdna] = actual.ramas[i]; } nuevo.cuenta = (orden - 1) - posMdna; /* numero de claves en el nuevo nodo*/ actual.cuenta = posMdna; // numero claves en el nodo origen /* Es insertada la clave y rama en el nodo que le corresponde*/ if (k <= orden / 2) //si k es menor al minimo de claves que puede haber en la pagina { meterHoja(actual, valor, rd, k); //inserta en el nodo origen } else { meterHoja(nuevo, valor, rd, k - posMdna); //se inserta el nuevo valor que traiamos en el nodo nuevo } /* se extrae clave mediana del nodo origen*/ mediana = actual.claves[actual.cuenta]; /* Rama0 del nuevo nodo es la rama de la mediana*/ nuevo.ramas[0] = actual.ramas[actual.cuenta]; actual.cuenta--; }
public Arbol_B(int orden) { this.orden = orden; this.raiz = null; }