+++ /dev/null
-#include <iostream.h>\r
-#include <stdlib.h>\r
-\r
-#define TAMANO 1000\r
-\r
-struct stclave {\r
- int valor;\r
- long registro;\r
-};\r
-\r
-class bnodo {\r
- public:\r
- bnodo(int nClaves); // Constructor\r
- ~bnodo(); // Destructor\r
- \r
- private:\r
- int clavesUsadas; // Claves usadas en el nodo\r
- stclave *clave; // Array de claves del nodo\r
- bnodo **puntero; // Array de punteros a bnodo\r
- bnodo *padre; // Puntero a nodo padre\r
-\r
- friend class btree;\r
-};\r
-\r
-typedef bnodo *pbnodo;\r
-\r
-bnodo::bnodo(int nClaves)\r
-{\r
- clavesUsadas = 0;\r
- clave = new stclave[nClaves];\r
- puntero = new pbnodo[nClaves+1];\r
- padre = NULL;\r
-}\r
-\r
-bnodo::~bnodo()\r
-{\r
- delete[] clave;\r
- delete[] puntero;\r
-}\r
-\r
-class btree {\r
- public:\r
- btree(int nClv);\r
- ~btree();\r
- long Buscar(int clave);\r
- bool Insertar(stclave clave);\r
- void Borrar(int clave);\r
- void Mostrar();\r
-\r
- private:\r
- stclave *lista;\r
- pbnodo *listapunt;\r
- void Inserta(stclave clave, pbnodo nodo, pbnodo hijo1, pbnodo hijo2);\r
- void BorrarClave(pbnodo nodo, int valor);\r
- void BorrarNodo(pbnodo nodo);\r
- void PasarClaveDerecha(pbnodo derecha, pbnodo padre, pbnodo nodo, int posClavePadre);\r
- void PasarClaveIzquierda(pbnodo izquierda, pbnodo padre, pbnodo nodo, int posClavePadre);\r
- void FundirNodo(pbnodo izquierda, pbnodo &padre, pbnodo derecha, int posClavePadre);\r
- void Ver(pbnodo nodo);\r
- int nClaves, nodosMinimos;\r
- pbnodo Entrada;\r
-};\r
-\r
-btree::btree(int nClv) : nClaves(nClv)\r
-{\r
- lista = new stclave[nClaves+1];\r
- listapunt = new pbnodo[nClaves+2];\r
- nodosMinimos = nClaves/2; // ((nClaves+1)/2)-1;\r
- Entrada = NULL;\r
-}\r
-\r
-btree::~btree()\r
-{\r
- delete[] lista;\r
- delete[] listapunt;\r
- // Destruir árbol, algoritmo recursivo:\r
- BorrarNodo(Entrada);\r
-}\r
-\r
-void btree::BorrarNodo(pbnodo nodo)\r
-{\r
- int i;\r
-\r
- if(!nodo) return;\r
- for(i = 0; i <= nodo->clavesUsadas; i++) BorrarNodo(nodo->puntero[i]);\r
- delete nodo;\r
-}\r
-\r
-void btree::Mostrar()\r
-{\r
- cout << "arbol" << endl;\r
- Ver(Entrada);\r
- cout << "-----" << endl;\r
-}\r
-\r
-void btree::Ver(pbnodo nodo)\r
-{\r
- int i;\r
-\r
- if(!nodo) return;\r
- for(i = 0; i < nodo->clavesUsadas-1; i++) cout << nodo->clave[i].valor << "-";\r
- if(nodo->clavesUsadas) cout << nodo->clave[i].valor << " [";\r
- if(nodo->padre) cout << (nodo->padre)->clave[0].valor; else cout << "*";\r
- cout << "]" << endl;\r
- for(i = 0; i <= nodo->clavesUsadas; i++) Ver(nodo->puntero[i]);\r
-}\r
-\r
-long btree::Buscar(int clave)\r
-{\r
- pbnodo nodo = Entrada;\r
- int i;\r
-\r
- while(nodo) {\r
- i = 0;\r
- while(i < nodo->clavesUsadas && (nodo->clave[i].valor < clave)) i++;\r
- if(nodo->clave[i].valor == clave) return nodo->clave[i].registro;\r
- else nodo = nodo->puntero[i];\r
- }\r
- return -1L;\r
-}\r
-\r
-bool btree::Insertar(stclave clave)\r
-{\r
- pbnodo nodo, padre;\r
- int i;\r
-\r
- // Asegurarse de que la clave no está en el árbol\r
- padre = nodo = Entrada;\r
- while(nodo) {\r
- padre = nodo;\r
- i = 0;\r
- while(i < nodo->clavesUsadas && (nodo->clave[i].valor < clave.valor)) i++;\r
- if(nodo->clave[i].valor == clave.valor && i < nodo->clavesUsadas) return false;\r
- else nodo = nodo->puntero[i];\r
- }\r
- nodo = padre;\r
- Inserta(clave, nodo, NULL, NULL);\r
- return true;\r
-}\r
-\r
-void btree::Inserta(stclave clave, pbnodo nodo, pbnodo hijo1, pbnodo hijo2)\r
-{\r
- pbnodo padre, nuevo;\r
- int i, j;\r
- bool salir = false;\r
-\r
- // Insertar nueva clave en nodo:\r
- do {\r
- if(!nodo)\r
- {\r
- nodo = new bnodo(nClaves);\r
- nodo->clavesUsadas = 0;\r
- nodo->padre = NULL;\r
- Entrada = nodo;\r
- }\r
- padre = nodo->padre;\r
- if(nodo->clavesUsadas == nClaves) // overflow\r
- {\r
- // Nodo derecho\r
- nuevo = new bnodo(nClaves);\r
- // Construye lista ordenada:\r
- i = 0;\r
- while(nodo->clave[i].valor < clave.valor && i < nClaves) {\r
- lista[i] = nodo->clave[i];\r
- listapunt[i] = nodo->puntero[i];\r
- i++;\r
- }\r
- lista[i] = clave;\r
- listapunt[i] = hijo1;\r
- listapunt[i+1] = hijo2;\r
- while(i < nClaves) {\r
- lista[i+1] = nodo->clave[i];\r
- listapunt[i+2] = nodo->puntero[i+1];\r
- i++;\r
- }\r
- // Dividir nodos:\r
- // Nodo izquierdo:\r
- nodo->clavesUsadas = nClaves/2;\r
- for(j = 0; j < nodo->clavesUsadas; j++) {\r
- nodo->clave[j] = lista[j];\r
- nodo->puntero[j] = listapunt[j];\r
- }\r
- nodo->puntero[nodo->clavesUsadas] = listapunt[nodo->clavesUsadas];\r
-\r
- // Nodo derecho:\r
- nuevo->clavesUsadas = nClaves - nodo->clavesUsadas;\r
- for(j = 0; j < nuevo->clavesUsadas; j++) {\r
- nuevo->clave[j] = lista[j+(nClaves/2)+1];\r
- nuevo->puntero[j] = listapunt[j+(nClaves/2)+1];\r
- }\r
- nuevo->puntero[nuevo->clavesUsadas] = listapunt[nClaves+1];\r
-\r
- for(j = 0; j <= nodo->clavesUsadas; j++)\r
- if(nodo->puntero[j]) (nodo->puntero[j])->padre = nodo;\r
- for(j = 0; j <= nuevo->clavesUsadas; j++)\r
- if(nuevo->puntero[j]) (nuevo->puntero[j])->padre = nuevo;\r
-\r
- clave = lista[nClaves/2];\r
- hijo1 = nodo;\r
- hijo2 = nuevo;\r
- nodo = padre;\r
- }\r
- else\r
- {\r
- // Inserta nueva clave en su lugar:\r
- i = 0;\r
- if(nodo->clavesUsadas > 0) {\r
- while(nodo->clave[i].valor < clave.valor && i < nodo->clavesUsadas) i++;\r
- for(j = nodo->clavesUsadas; j > i; j--)\r
- nodo->clave[j] = nodo->clave[j-1];\r
- for(j = nodo->clavesUsadas+1; j > i; j--)\r
- nodo->puntero[j] = nodo->puntero[j-1];\r
- }\r
- nodo->clavesUsadas++;\r
- nodo->clave[i] = clave;\r
- nodo->puntero[i] = hijo1;\r
- nodo->puntero[i+1] = hijo2;\r
- if(hijo1) hijo1->padre = nodo;\r
- if(hijo2) hijo2->padre = nodo;\r
- salir = true;\r
- }\r
- } while(!salir);\r
-}\r
-\r
-void btree::Borrar(int valor)\r
-{\r
- pbnodo nodo;\r
- bool encontrado = false;\r
- int i;\r
-\r
- // Busca el nodo que contiene la clave, si existe\r
- nodo = Entrada;\r
- while(nodo && !encontrado) {\r
- i = 0;\r
- while(i < nodo->clavesUsadas && (nodo->clave[i].valor < valor)) i++;\r
- if(nodo->clave[i].valor == valor && i < nodo->clavesUsadas) encontrado = true;\r
- else nodo = nodo->puntero[i];\r
- }\r
- if(encontrado) BorrarClave(nodo, valor);\r
-}\r
-\r
-void btree::BorrarClave(pbnodo nodo, int valor)\r
-{\r
- pbnodo actual, derecha, izquierda, padre;\r
- int posClavePadre, pos, i;\r
-\r
- // Buscar posición dentro de lista de claves:\r
- pos = 0;\r
- while(nodo->clave[pos].valor < valor) pos++;\r
-\r
- // ¿Está la clave en un nodo hoja?\r
- if(nodo->puntero[0]) { // No, se trata de un nodo intermedio\r
- // Buscar actual del valor siguiente:\r
- actual = nodo->puntero[pos+1];\r
- while(actual->puntero[0]) actual = actual->puntero[0];\r
- // Intercambiar con el valor siguiente:\r
- nodo->clave[pos] = actual->clave[0];\r
- // La posición de la clave a borrar en ahora la 0:\r
- pos = 0;\r
- } else actual = nodo;\r
-\r
- // Borrar clave\r
- for(i = pos; i < actual->clavesUsadas; i++)\r
- actual->clave[i] = actual->clave[i+1];\r
- actual->clavesUsadas--;\r
-\r
- if(actual == Entrada && actual->clavesUsadas == 0) {\r
- delete actual;\r
- Entrada = NULL;\r
- return;\r
- }\r
-\r
- // ¿Es el número de claves mayor que el mínimo para el nodo?\r
- if(actual == Entrada || actual->clavesUsadas >= nodosMinimos) return;\r
-\r
- do {\r
- // El número de claves es menor que el mínimo:\r
- // Buscar nodos a derecha e izquierda:\r
- padre = actual->padre;\r
- for(posClavePadre = 0;\r
- padre->puntero[posClavePadre] != actual;\r
- posClavePadre++);\r
- if(posClavePadre > 0)\r
- izquierda = padre->puntero[posClavePadre-1];\r
- else izquierda = NULL;\r
- if(posClavePadre < padre->clavesUsadas)\r
- derecha = padre->puntero[posClavePadre+1];\r
- else derecha = NULL;\r
-\r
- // Intentar pasar una clave de un nodo cercano:\r
- if(derecha && derecha->clavesUsadas > nodosMinimos)\r
- PasarClaveDerecha(derecha, padre, actual, posClavePadre);\r
- else if(izquierda && izquierda->clavesUsadas > nodosMinimos)\r
- PasarClaveIzquierda(izquierda, padre, actual, posClavePadre-1);\r
- // Si no fue posible, fundir con un nodo cercano y una clave de padre:\r
- else if(derecha) // Usar nodo derecho\r
- FundirNodo(actual, padre, derecha, posClavePadre);\r
- else // Usar el nodo izquierdo\r
- FundirNodo(izquierda, padre, actual, posClavePadre-1);\r
- // Vuelta a empezar:\r
- actual = padre;\r
- } while(actual && actual != Entrada && actual->clavesUsadas < nodosMinimos);\r
-}\r
-\r
-void btree::PasarClaveDerecha(pbnodo derecha, pbnodo padre, pbnodo nodo, int posClavePadre)\r
-{\r
- int i;\r
-\r
- nodo->clave[nodo->clavesUsadas] = padre->clave[posClavePadre];\r
- nodo->clavesUsadas++;\r
- padre->clave[posClavePadre] = derecha->clave[0];\r
- nodo->puntero[nodo->clavesUsadas] = derecha->puntero[0];\r
- if(derecha->puntero[0]) derecha->puntero[0]->padre = nodo;\r
- for(i = 0; i < derecha->clavesUsadas; i++) derecha->clave[i] = derecha->clave[i+1];\r
- for(i = 0; i <= derecha->clavesUsadas; i++) derecha->puntero[i] = derecha->puntero[i+1];\r
- derecha->clavesUsadas--;\r
-}\r
-\r
-void btree::PasarClaveIzquierda(pbnodo izquierda, pbnodo padre, pbnodo nodo, int posClavePadre)\r
-{\r
- int i;\r
-\r
- for(i = nodo->clavesUsadas; i > 0; i--) nodo->clave[i] = nodo->clave[i-1];\r
- for(i = nodo->clavesUsadas+1; i > 0; i--) nodo->puntero[i] = nodo->puntero[i-1];\r
- nodo->clavesUsadas++;\r
- nodo->clave[0] = padre->clave[posClavePadre];\r
- padre->clave[posClavePadre] = izquierda->clave[izquierda->clavesUsadas-1];\r
- nodo->puntero[0] = izquierda->puntero[izquierda->clavesUsadas];\r
- if(nodo->puntero[0]) nodo->puntero[0]->padre = nodo;\r
- izquierda->clavesUsadas--;\r
-}\r
-\r
-void btree::FundirNodo(pbnodo izquierda, pbnodo &padre, pbnodo derecha, int posClavePadre)\r
-{\r
- int i;\r
-\r
- izquierda->clave[izquierda->clavesUsadas] = padre->clave[posClavePadre];\r
- padre->clavesUsadas--;\r
- for(i = posClavePadre; i < padre->clavesUsadas; i++) {\r
- padre->clave[i] = padre->clave[i+1];\r
- padre->puntero[i+1] = padre->puntero[i+2];\r
- }\r
- izquierda->clavesUsadas++;\r
- for(i = 0; i < derecha->clavesUsadas; i++)\r
- izquierda->clave[izquierda->clavesUsadas+i] = derecha->clave[i];\r
- for(i = 0; i <= derecha->clavesUsadas; i++) {\r
- izquierda->puntero[izquierda->clavesUsadas+i] = derecha->puntero[i];\r
- if(derecha->puntero[i]) derecha->puntero[i]->padre = izquierda;\r
- }\r
- izquierda->clavesUsadas += derecha->clavesUsadas;\r
- if(padre == Entrada && padre->clavesUsadas == 0) { // Cambio de entrada\r
- Entrada = izquierda;\r
- Entrada->padre = NULL;\r
- delete padre;\r
- padre = NULL;\r
- }\r
- delete derecha;\r
-}\r
-\r
-int main()\r
-{\r
- int matriz[TAMANO];\r
- btree arbol(500);\r
- stclave clave;\r
- int i;\r
-
-// srand(time(NULL));
- for(i = 0; i < TAMANO; i++) {
- do {
- matriz[i] = rand()%10000;
- clave.valor = matriz[i];
- clave.registro = i;
- } while(!arbol.Insertar(clave));
- }
-
- cout << "mostrar: " << endl;
- arbol.Mostrar();
-
- cout << "Buscar elemento 23: " << matriz[23] << " posicion: " <<\r
- arbol.Buscar(matriz[23]) << endl;\r
-
- for(i = 0; i < TAMANO; i++) {\r
- cout << "Borrar: [" << i << "]: " << matriz[i] << endl;\r
- arbol.Borrar(matriz[i]);\r
-// arbol.Mostrar();\r
- }\r
- arbol.Mostrar();\r
- return 0;\r
-}\r