Beispiel #1
0
 /// <summary>
 /// Metodo para eliminar el sucesor de un nodo
 /// </summary>
 /// <param name="nodo">nodo a eliminar</param>
 /// <returns>valor contenido</returns>
 private Entry <TKey, T> EliminarSucesor(BNodo <TKey, T> nodo)
 {
     if (nodo.EsHoja)
     {
         var result = nodo.Entradas[0];
         nodo.Entradas.RemoveAt(0);
         return(result);
     }
     return(this.EliminarPredecesor(nodo.Hijos.First()));
 }
Beispiel #2
0
 /// <summary>
 /// Metodo para eliminar el predecesor de un nodo
 /// </summary>
 /// <param name="nodo">nodo a eliminar</param>
 /// <returns>valor contenido</returns>
 private Entry <TKey, T> EliminarPredecesor(BNodo <TKey, T> nodo)
 {
     if (nodo.EsHoja)
     {
         var result = nodo.Entradas[nodo.Entradas.Count - 1];
         nodo.Entradas.RemoveAt(nodo.Entradas.Count - 1);
         return(result);
     }
     return(this.EliminarPredecesor(nodo.Hijos.Last()));
 }
Beispiel #3
0
        /// <summary>
        /// Metodo para realizar un busqueda interna entre nodos
        /// </summary>
        /// <param name="node">nodo a buscar</param>
        /// <param name="key">llave a buscar</param>
        /// <returns>valor buscado</returns>
        private Entry <TKey, T> BusquedaInterna(BNodo <TKey, T> node, TKey key)
        {
            int i = node.Entradas.TakeWhile(entry => key.CompareTo(entry.LLave) > 0).Count();

            if (i < node.Entradas.Count && node.Entradas[i].LLave.CompareTo(key) == 0)
            {
                return(node.Entradas[i]);
            }
            return(node.EsHoja ? null : this.BusquedaInterna(node.Hijos[i], key));
        }
Beispiel #4
0
        /// <summary>
        /// Metodo para eliminar de manera interna una llave
        /// </summary>
        /// <param name="nodo">nodo a buscar</param>
        /// <param name="LlaveEliminar">llave a eliminar</param>
        private void EliminarInterno(BNodo <TKey, T> nodo, TKey LlaveEliminar)
        {
            int i = nodo.Entradas.TakeWhile(entrada => LlaveEliminar.CompareTo(entrada.LLave) > 0).Count();

            // Encontro la llave en un nodo, la elimina
            if (i < nodo.Entradas.Count && nodo.Entradas[i].LLave.CompareTo(LlaveEliminar) == 0)

            {
                this.EliminarLlaveNodo(nodo, LlaveEliminar, i);

                return;
            }
            // Eliminar la lleva de un sub arbol
            if (!nodo.EsHoja)
            {
                this.EliminarLlaveSubArbol(nodo, LlaveEliminar, i);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Metodo que permite dividir un nodo, en 2 nodos y obtener los rangos permitidos segun el grado
        /// </summary>
        /// <param name="padreNodo">raiz o padre</param>
        /// <param name="nodoCorrer">Nodo que se va dividir</param>
        /// <param name="nodoMover">Nodo a mover y cambiar de ubicacion</param>
        private void DividirHijo(BNodo <TKey, T> padreNodo, int nodoCorrer, BNodo <TKey, T> nodoMover)
        {
            var nuevoNodo = new BNodo <TKey, T>(this.Grado);

            if (Grado % 2 == 0)
            {
                padreNodo.Entradas.Insert(nodoCorrer, nodoMover.Entradas[(this.Grado / 2) - 1]);
            }
            else
            {
                padreNodo.Entradas.Insert(nodoCorrer, nodoMover.Entradas[(this.Grado / 2)]);
            }

            if (Grado % 2 == 0)
            {
                nuevoNodo.Entradas.AddRange(nodoMover.Entradas.GetRange((this.Grado / 2), (this.Grado / 2)));
                nodoMover.Entradas.RemoveRange((this.Grado / 2) - 1, (this.Grado / 2) + 1);
            }
            else
            {
                nuevoNodo.Entradas.AddRange(nodoMover.Entradas.GetRange((this.Grado / 2) + 1, this.Grado / 2));
                nodoMover.Entradas.RemoveRange((this.Grado / 2), (this.Grado / 2) + 1);
            }



            if (!nodoMover.EsHoja)
            {
                if (Grado % 2 == 0)
                {
                    nuevoNodo.Hijos.AddRange(nodoMover.Hijos.GetRange((this.Grado / 2), (this.Grado / 2) + 1));
                    nodoMover.Hijos.RemoveRange((this.Grado / 2), (this.Grado / 2) + 1);
                }
                else
                {
                    nuevoNodo.Hijos.AddRange(nodoMover.Hijos.GetRange((this.Grado / 2) + 1, (this.Grado / 2) + 1));
                    nodoMover.Hijos.RemoveRange((this.Grado / 2) + 1, (this.Grado / 2) + 1);
                }
            }
            padreNodo.Hijos.Insert(nodoCorrer + 1, nuevoNodo);
        }
Beispiel #6
0
        /// <summary>
        /// Metodo para elminar la llave de un nodo, es decir, un nodo raiz
        /// </summary>
        /// <param name="nodo">nodo </param>
        /// <param name="LlaveEliminar">llave del nodo</param>
        /// <param name="indiceLlaveNodo">ubicacion</param>
        private void EliminarLlaveNodo(BNodo <TKey, T> nodo, TKey LlaveEliminar, int indiceLlaveNodo)
        {
            if (nodo.EsHoja)
            {
                nodo.Entradas.RemoveAt(indiceLlaveNodo);
                return;
            }
            BNodo <TKey, T> predecesorHijo = nodo.Hijos[indiceLlaveNodo];

            if (predecesorHijo.Entradas.Count >= this.Grado)
            {
                Entry <TKey, T> predecessor = this.EliminarPredecesor(predecesorHijo);
                nodo.Entradas[indiceLlaveNodo] = predecessor;
            }
            else
            {
                BNodo <TKey, T> succesorHijo = nodo.Hijos[indiceLlaveNodo + 1];
                if (succesorHijo.Entradas.Count >= this.Grado)
                {
                    Entry <TKey, T> successor = this.EliminarSucesor(predecesorHijo);
                    nodo.Entradas[indiceLlaveNodo] = successor;
                }
                else
                {
                    predecesorHijo.Entradas.Add(nodo.Entradas[indiceLlaveNodo]);
                    predecesorHijo.Entradas.AddRange(succesorHijo.Entradas);
                    predecesorHijo.Hijos.AddRange(succesorHijo.Hijos);



                    nodo.Entradas.RemoveAt(indiceLlaveNodo);
                    nodo.Hijos.RemoveAt(indiceLlaveNodo + 1);
                    this.EliminarInterno(predecesorHijo, LlaveEliminar);
                }
            }
        }
Beispiel #7
0
        private void InsertarRecursivo(BNodo <TKey, T> nodo, TKey nuevaLlave, T nuevoApuntador, BNodo <TKey, T> nodoPadre)
        {
            int posicionInsertar = nodo.Entradas.TakeWhile(entry => nuevaLlave.CompareTo(entry.LLave) >= 0).Count();

            //Es hoja
            if (nodo.EsHoja)
            {
                if (this.Raiz == nodo)
                {
                    this.Raiz.Entradas.Insert(posicionInsertar, new Entry <TKey, T>()
                    {
                        LLave = nuevaLlave, Apuntador = nuevoApuntador
                    });
                    if (this.Raiz.AlcanzaMaximaEntrada)
                    {
                        // nuevo nodo y se necesita dividir
                        BNodo <TKey, T> viejaRaiz = this.Raiz;
                        this.Raiz = new BNodo <TKey, T>(this.Grado);
                        this.Raiz.Hijos.Add(viejaRaiz);
                        this.DividirHijo(this.Raiz, 0, viejaRaiz);
                        this.Altura++;
                    }
                    return;
                }
                else
                {
                    nodo.Entradas.Insert(posicionInsertar, new Entry <TKey, T>()
                    {
                        LLave = nuevaLlave, Apuntador = nuevoApuntador
                    });
                    if (nodo.AlcanzaMaximaEntrada)
                    {
                        posicionInsertar = nodoPadre.Entradas.TakeWhile(entry => nuevaLlave.CompareTo(entry.LLave) >= 0).Count();
                        DividirHijo(nodoPadre, posicionInsertar, nodo);
                    }
                    return;
                }
            }
            //No es Hoja
            else
            {
                this.InsertarRecursivo(nodo.Hijos[posicionInsertar], nuevaLlave, nuevoApuntador, nodo);
                if (nodoPadre == null)
                {
                    if (nodo.AlcanzaMaximaEntrada)
                    {
                        BNodo <TKey, T> viejaRaiz = this.Raiz;
                        this.Raiz = new BNodo <TKey, T>(this.Grado);
                        this.Raiz.Hijos.Add(viejaRaiz);
                        this.DividirHijo(this.Raiz, 0, viejaRaiz);
                        this.Altura++;
                    }
                    return;
                }
                else
                {
                    if (nodo.AlcanzaMaximaEntrada)
                    {
                        DividirHijo(nodoPadre, posicionInsertar, nodo);
                    }
                    return;
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Metodo para eliminar la llave de un subarbol,es decir, valor raiz
        /// </summary>
        /// <param name="NodoPadre">raiz</param>
        /// <param name="LlaveEliminar">valor a eliminar</param>
        /// <param name="IndiceSubArbol">ubicacion del valor</param>
        private void EliminarLlaveSubArbol(BNodo <TKey, T> NodoPadre, TKey LlaveEliminar, int IndiceSubArbol)
        {
            BNodo <TKey, T> NodoHijo = NodoPadre.Hijos[IndiceSubArbol];


            if (NodoHijo.AlcanzaMinimaEntrada)
            {
                int             indiceIzquierdo = IndiceSubArbol - 1;
                BNodo <TKey, T> HijoIzquierdo   = IndiceSubArbol > 0 ? NodoPadre.Hijos[indiceIzquierdo] : null;
                int             indiceDerecho   = IndiceSubArbol + 1;
                BNodo <TKey, T> HijoDerecho     = IndiceSubArbol < NodoPadre.Hijos.Count - 1 ? NodoPadre.Hijos[indiceDerecho] : null;
                if (HijoIzquierdo != null && HijoIzquierdo.Entradas.Count > this.Grado - 1)
                {
                    NodoHijo.Entradas.Insert(0, NodoPadre.Entradas[IndiceSubArbol]);
                    NodoPadre.Entradas[IndiceSubArbol] = HijoIzquierdo.Entradas.Last();
                    HijoIzquierdo.Entradas.RemoveAt(HijoIzquierdo.Entradas.Count - 1);

                    if (!HijoIzquierdo.EsHoja)
                    {
                        NodoHijo.Hijos.Insert(0, HijoIzquierdo.Hijos.Last());
                        HijoIzquierdo.Hijos.RemoveAt(HijoIzquierdo.Hijos.Count - 1);
                    }
                }
                else if (HijoDerecho != null && HijoDerecho.Entradas.Count > this.Grado - 1)
                {
                    NodoHijo.Entradas.Add(NodoPadre.Entradas[IndiceSubArbol]);
                    NodoPadre.Entradas[IndiceSubArbol] = HijoDerecho.Entradas.First();
                    HijoDerecho.Entradas.RemoveAt(0);

                    if (!HijoDerecho.EsHoja)
                    {
                        NodoHijo.Hijos.Add(HijoDerecho.Hijos.First());
                        HijoDerecho.Hijos.RemoveAt(0);
                    }
                }
                else
                {
                    if (HijoIzquierdo != null)
                    {
                        NodoHijo.Entradas.Insert(0, NodoPadre.Entradas[IndiceSubArbol - 1]);
                        var oldEntries = NodoHijo.Entradas;
                        NodoHijo.Entradas = HijoIzquierdo.Entradas;
                        NodoHijo.Entradas.AddRange(oldEntries);
                        if (!HijoIzquierdo.EsHoja)
                        {
                            var oldChildren = NodoHijo.Hijos;
                            NodoHijo.Hijos = HijoIzquierdo.Hijos;
                            NodoHijo.Hijos.AddRange(oldChildren);
                        }
                        NodoPadre.Hijos.RemoveAt(indiceIzquierdo);
                        NodoPadre.Entradas.RemoveAt(IndiceSubArbol - 1);
                    }
                    else
                    {
                        Debug.Assert(HijoDerecho != null, "Nodo debe tener por lo menos un hermano");

                        NodoHijo.Entradas.Add(NodoPadre.Entradas[IndiceSubArbol]);
                        NodoHijo.Entradas.AddRange(HijoDerecho.Entradas);
                        if (!HijoDerecho.EsHoja)

                        {
                            NodoHijo.Hijos.AddRange(HijoDerecho.Hijos);
                        }
                        NodoPadre.Hijos.RemoveAt(indiceDerecho);
                        NodoPadre.Entradas.RemoveAt(IndiceSubArbol);
                    }
                }
            }
            this.EliminarInterno(NodoHijo, LlaveEliminar);
        }