public ArbolB(int orden, string nombreArchivo, IFabricaTextoTamañoFijo <T> fabrica) { // Se guardan los parámetros recibidos _archivoNombre = nombreArchivo; _fabrica = fabrica; // Se abre la conexión al archivo _archivo = new FileStream(_archivoNombre, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read); // Se obtienen los valores del encabezado del archivo _raiz = Utilidades.LeerEntero(_archivo, 0); _ultimaPosicionLibre = Utilidades.LeerEntero(_archivo, 1); Tamaño = Utilidades.LeerEntero(_archivo, 2); Orden = Utilidades.LeerEntero(_archivo, 3); Altura = Utilidades.LeerEntero(_archivo, 4); // Se corrigen los valores del encabezado cuando el archivos no existe previamente if (_ultimaPosicionLibre == Utilidades.ApuntadorVacio) { _ultimaPosicionLibre = 0; } if (Tamaño == Utilidades.ApuntadorVacio) { Tamaño = 0; } if (Orden == Utilidades.ApuntadorVacio) { Orden = orden; } if (Altura == Utilidades.ApuntadorVacio) { Altura = 1; } if (_raiz == Utilidades.ApuntadorVacio) { // Se crea la cabeza del árbol vacía // para evitar futurs errores NodoB <T> nodoCabeza = new NodoB <T>(Orden, _ultimaPosicionLibre, Utilidades.ApuntadorVacio, _fabrica); _ultimaPosicionLibre++; _raiz = nodoCabeza.Posicion; nodoCabeza.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); } // Si el archivo existe solamente se actualizan los encabezados, sino // se crea y luego se almacenan los valores iniciales GuardarEncabezado(); }
private void Subir(NodoB <T> nodoActual, string llave, T dato, int hijoDerecho) { // Si el nodo no está lleno, se agrega la información // al nodo y el método termina if (!nodoActual.Lleno) { nodoActual.AgregarDato(llave, dato, hijoDerecho); nodoActual.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); return; } // Creo un nuevo nodo hermano NodoB <T> nuevoHermano = new NodoB <T>(Orden, _ultimaPosicionLibre, nodoActual.Padre, _fabrica); _ultimaPosicionLibre++; // Datos a subir al padre luego de la separación string llavePorSubir = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; T datoPorSubir = _fabrica.FabricarNulo(); // Se llama al método que hace la separación nodoActual.SepararNodo(llave, dato, hijoDerecho, nuevoHermano, ref llavePorSubir, ref datoPorSubir); // Actualizar el apuntador en todos los hijos NodoB <T> nodoHijo = null; for (int i = 0; i < nuevoHermano.Hijos.Count; i++) { if (nuevoHermano.Hijos[i] != Utilidades.ApuntadorVacio) { // Se carga el hijo para modificar su apuntador al padre nodoHijo = NodoB <T> .LeerNodoDesdeDisco(_archivo, _tamañoEncabezadoBinario, Orden, nuevoHermano.Hijos[i], _fabrica); nodoHijo.Padre = nuevoHermano.Posicion; nodoHijo.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); } else { break; } } // Evaluo el caso del Padre if (nodoActual.Padre == Utilidades.ApuntadorVacio) // Es la raiz { // Creo un nuevo nodo Raiz NodoB <T> nuevaRaiz = new NodoB <T>(Orden, _ultimaPosicionLibre, Utilidades.ApuntadorVacio, _fabrica); _ultimaPosicionLibre++; Altura++; // Agrego la información nuevaRaiz.Hijos[0] = nodoActual.Posicion; nuevaRaiz.AgregarDato(llavePorSubir, datoPorSubir, nuevoHermano.Posicion); // Actualizo los apuntadores al padre nodoActual.Padre = nuevaRaiz.Posicion; nuevoHermano.Padre = nuevaRaiz.Posicion; _raiz = nuevaRaiz.Posicion; // Guardo los cambios nuevaRaiz.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); nodoActual.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); nuevoHermano.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); } else // No es la raiz { nodoActual.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); nuevoHermano.GuardarNodoEnDisco(_archivo, _tamañoEncabezadoBinario); // Cargar el nodo Padre NodoB <T> nodoPadre = NodoB <T> .LeerNodoDesdeDisco(_archivo, _tamañoEncabezadoBinario, Orden, nodoActual.Padre, _fabrica); Subir(nodoPadre, llavePorSubir, datoPorSubir, nuevoHermano.Posicion); } }