private BEntry <TKey, T> EliminarSucesor(NodoAsteriscoo <TKey, T> nodo) { if (nodo.EsHoja) { var result = nodo.Entradas[0]; nodo.Entradas.RemoveAt(0); return(result); } return(this.EliminarPredecesor(nodo.Hijos.First())); }
private BEntry <TKey, T> BusquedaInterna(NodoAsteriscoo <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)); }
private void EliminarInterno(NodoAsteriscoo <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.EliminarLlaveSuArbolAsterisco(nodo, LlaveEliminar, i); } }
// cuando el nodo se llena y se crean dos hijos private void DividirHijo(NodoAsteriscoo <TKey, T> padreNodo, int nodoCorrer, NodoAsteriscoo <TKey, T> nodoMover) { var nuevoNodo = new NodoAsteriscoo <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); }
private void EliminarLlaveNodo(NodoAsteriscoo <TKey, T> nodo, TKey LlaveEliminar, int indiceLlaveNodo) { if (nodo.EsHoja) { nodo.Entradas.RemoveAt(indiceLlaveNodo); return; } NodoAsteriscoo <TKey, T> predecesorHijo = nodo.Hijos[indiceLlaveNodo]; if (predecesorHijo.Entradas.Count >= this.Grado) { BEntry <TKey, T> predecessor = this.EliminarPredecesor(predecesorHijo); nodo.Entradas[indiceLlaveNodo] = predecessor; } else { NodoAsteriscoo <TKey, T> succesorHijo = nodo.Hijos[indiceLlaveNodo + 1]; if (succesorHijo.Entradas.Count >= this.Grado) { BEntry <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); } } }
private void InsertarRecursivo(NodoAsteriscoo <TKey, T> nodo, TKey nuevaLlave, T nuevoApuntador, NodoAsteriscoo <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 BEntry <TKey, T>() { LLave = nuevaLlave, Apuntador = nuevoApuntador }); if (this.Raiz.AlcanzaMaximaEntrada) { // nuevo nodo y se necesita dividir NodoAsteriscoo <TKey, T> viejaRaiz = this.Raiz; this.Raiz = new NodoAsteriscoo <TKey, T>(this.Grado); this.Raiz.Hijos.Add(viejaRaiz); this.DividirHijo(this.Raiz, 0, viejaRaiz); this.Altura++; } return; } else { nodo.Entradas.Insert(posicionInsertar, new BEntry <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) { NodoAsteriscoo <TKey, T> viejaRaiz = this.Raiz; this.Raiz = new NodoAsteriscoo <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; } } }
private void EliminarLlaveSuArbolAsterisco(NodoAsteriscoo <TKey, T> NodoPadre, TKey LlaveEliminar, int IndiceSuArbolAsterisco) { NodoAsteriscoo <TKey, T> NodoHijo = NodoPadre.Hijos[IndiceSuArbolAsterisco]; //para que no se creen mas hojas sin que sirvan if (NodoHijo.AlcanzaMinimaEntrada) { int indiceIzquierdo = IndiceSuArbolAsterisco - 1; NodoAsteriscoo <TKey, T> HijoIzquierdo = IndiceSuArbolAsterisco > 0 ? NodoPadre.Hijos[indiceIzquierdo] : null; int indiceDerecho = IndiceSuArbolAsterisco + 1; NodoAsteriscoo <TKey, T> HijoDerecho = IndiceSuArbolAsterisco < NodoPadre.Hijos.Count - 1 ? NodoPadre.Hijos[indiceDerecho] : null; if (HijoIzquierdo != null && HijoIzquierdo.Entradas.Count > this.Grado - 1) { NodoHijo.Entradas.Insert(0, NodoPadre.Entradas[IndiceSuArbolAsterisco]); NodoPadre.Entradas[IndiceSuArbolAsterisco] = 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[IndiceSuArbolAsterisco]); NodoPadre.Entradas[IndiceSuArbolAsterisco] = 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[IndiceSuArbolAsterisco - 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(IndiceSuArbolAsterisco - 1); } else { Debug.Assert(HijoDerecho != null, "Nodo debe tener por lo menos un hermano"); NodoHijo.Entradas.Add(NodoPadre.Entradas[IndiceSuArbolAsterisco]); NodoHijo.Entradas.AddRange(HijoDerecho.Entradas); if (!HijoDerecho.EsHoja) { NodoHijo.Hijos.AddRange(HijoDerecho.Hijos); } NodoPadre.Hijos.RemoveAt(indiceDerecho); NodoPadre.Entradas.RemoveAt(IndiceSuArbolAsterisco); } } } this.EliminarInterno(NodoHijo, LlaveEliminar); }