Arboles B y B+
Presentacion
Tabla de contenido
Introducción
…………………………………………………………………….. 3
Teoría
…………………………………………………………………….. 4
Búsquedas
…………………………………………………………………….. 6
Inserciones
…………………………………………………………………….. 9
Eliminaciones …………………………………………………………………….. 12 Diferencias entre Arboles B y B+ ………….…………………………………….. 15 Conclusión
…………………………………………………………………….. 16
Bibliografía
…………………………………………………………………….. 17
Introducción 2
Conocerlos los Arboles B y B+ que representan las diferentes estructuras que poseen los arboles de búsqueda teniendo en cuenta que varían según la cantidad de nodos hijos que tengan, debido a que estos tipos de árboles se han convertido en la forma más utilizada para la organización de archivos indizados. El saber la forma en cómo se comporta el árbol teniendo en cuenta las inserciones y eliminaciones y conocer la los métodos con sus respectivas implementaciones en el lenguaje java.
3
Teoría
Árbol B: Son arboles balanceados de búsqueda en los cuales cada nodo puede poseer más de dos hijos, este tipo de árboles mantienen los datos ordenados y al momento de realizar las inserciones y eliminaciones se realizan de manera logarítmica. La idea es que los nodos internos deben tener un número variable de nodos hijos dentro de un rango predeterminado, entonces cuando se inserta o se hace la eliminación de un dato de la estructura, la cantidad de nodos hijos solo varia dentro de un nodo. Para que el árbol siga siendo balanceado se mantienen el número de nodos dentro del rango que ya está definido, dependiendo del número los nodos internos se juntan o se parten. Debido a que se permite tener un rango de nodos hijos, este tipo de árbol no necesita rebalancearse de forma tan frecuente como los arboles binarios de Búsqueda. Una desventaja de este tipo de árbol es que pueden desperdiciar memoria, debido a que los nodos no están ocupados en su totalidad. El árbol B se mantiene balanceado porque se requiere que todos los nodos hoja se encuentren a la misma altura. La altura de un Árbol B en el mejor de los casos está definida por: Y en el peor de los casos, altura de un Árbol B está definida por: Donde m es el número máximo de hijos que puede tener un nodo. La estructura de un nodo interno de este tipo de árbol es la siguiente: Cada nodo interno actúa como un valor separador, que lo subdividen subárboles. Es decir, si un nodo tiene tres nodos hijos, debe tener dos valores separadores a1 y a2. Todos los valores del subárbol izquierdo deben ser menores a a1, Todos los valores del subárbol del centro deben estar entre a1 y a2, y todos los valores del subárbol derecho deben ser mayores a a2.
Árbol B+: Es un tipo de estructura de datos de árbol que se encuentran comúnmente en las implementaciones de bases de datos y sistemas de archivos, representa una colección de datos ordenados de manera que se permite una inserción y borrado eficientes de elementos. Es un índice, multinivel, dinámico, con un límite máximo y mínimo en el número de claves por nodo. Un árbol B+ es una variación de un árbol B.
4
En un árbol B+, toda la información se guarda en las hojas. Los nodos internos sólo contienen claves y punteros. Todas las hojas se encuentran en el mismo nivel, que corresponde al más bajo. Los nodos hoja se encuentran unidos entre sí como una lista enlazada para permitir búsqueda secuencial.
Posee las siguientes Características:
El número máximo de claves en un registro es llamado el orden del árbol B+. El mínimo número de claves por registro es la mitad del máximo número de claves. Por ejemplo, si el orden de un árbol B+ es n, cada nodo (exceptuando la raíz) debe tener entre n/2 y n claves. El número de claves que pueden ser indexadas usando un árbol B+ está en función del orden del árbol y su altura.
5
Búsquedas: Árbol B: La búsqueda es similar a la de los arboles binarios, debido a que se inicia en la raíz, y se recorre hacia abajo, escogiendo el sub-nodo a buscar teniendo en cuenta la posición relativa. Siguiendo este proceso: 1. 2. 3. 4. 5. 6. 7. 8. 9.
Situarse en el nodo raíz. Comprobar si contiene la clave a buscar. Encontrada fin de procedimiento. No encontrada: Si es hoja no existe la clave. En otro caso el nodo actual es el hijo que corresponde: La clave a buscar k < k1: hijo izquierdo. La clave a buscar k > ki y k < ki+1 hijo. Volver a paso 2.
Implementación en java: /** * Buscar una clave dentro del arbol. * @param c Clave a buscar. * @return Posicion de la pagina donde se encuentra la clave, -1 si no esta. * @throws IOException * @throws ClassNotFoundException */ public int buscar(Clave c) throws IOException, ClassNotFoundException { if (this.vacio()) return -1; else return buscar(c,1); // 1 posicion de la raiz; } /** * Buscar una clave dentro del arbol cuya raiz esta en la posicion pos. * @param c Clave a buscar. * @param pos Posicion de la raiz. * @return Posicion de la pagina donde se encuentra la clave, -1 si no esta. * @throws IOException 6
* @throws ClassNotFoundException */ private int buscar(Clave c, int pos) throws IOException, ClassNotFoundException { if (pos != -1) { Pagina p = new Pagina(this.orden); this.read(p,pos); int posicion = p.descendiente(c); if (posicion
7
Árbol B+: Se cumple de igual forma que en árbol B y se sigue el siguiente proceso: 1. Situarse en el nodo raíz. 2. Comprobar si contiene la clave a buscar. 3. Encontrada fin de procedimiento. 4. No encontrada: 5. Si es hoja no existe la clave. 6. En otro caso el nodo actual es el hijo que corresponde: La clave a buscar k <> ki y k <> Implementación en java: void Buscar_Nodo(int clave) { int pos, i, n; struct nodo *ptr = root; printf(" El camino del arbol:\n"); while (ptr) { n = ptr->n; for (i=0; i < ptr->n; i++) printf("\t%d",ptr->arreglo_claves[i]); printf("\n"); pos = BuscarPosicion(clave, ptr->arreglo_claves, n); if (pos < n && clave == ptr->arreglo_claves[pos]) { printf("\t\t\t La clave %d fue encontrada\n",clave,i); return; } ptr = ptr->p[pos]; } printf("\t\t\t La clave No %d fue encontrada\n",clave); }
int BuscarPosicion(int clave, int *key_arr, int n) { int pos=0; while (pos < n && clave > key_arr[pos]) pos++; return pos; }
8
Inserciones Árbol B: Las inserciones se realizan sobre los nodos hojas, llevando a cabo los siguientes pasos: 1. Realizando una búsqueda en el árbol, se halla el nodo hoja en el cual debería ubicarse el nuevo elemento. 2. Si el nodo hoja tiene menos elementos que el máximo número de elementos legales, entonces hay lugar para uno más. Inserte el nuevo elemento en el nodo, respetando el orden de los elementos. 3. De otra forma, el nodo debe ser dividido en dos nodos. La división se realiza de la siguiente manera: 3.1 Se escoge el valor medio entre los elementos del nodo y el nuevo elemento. 3.2 Los valores menores que el valor medio se colocan en el nuevo nodo izquierdo, y los valores mayores que el valor medio se colocan en el nuevo nodo derecho; el valor medio actúa como valor separador. 3.3 El valor separador se debe colocar en el nodo padre, lo que puede provocar que el padre sea dividido en dos, y así sucesivamente.
De igual forma, si las divisiones de nodos suben hasta la raíz, se crea una nueva raíz con un único elemento como valor separador, y dos hijos, esa es la razón por la cual la cota inferior del tamaño de los nodos no se ve aplicada en la raíz. Implementación en java:
/** * Inserta la clave c en el arbol b. * @param c Clave a insertar. * @throws IOException * @throws ClassNotFoundException */ public void insert(Clave c) throws IOException, ClassNotFoundException { if (this.vacio()) { Pagina p = new Pagina(this.orden); p.insert(c); this.add(p);
9
} else { long sobre = this.insert(c,1); // 1 indica posicion de la pagina raiz if (sobre != -1) { Pagina izq = new Pagina(this.orden); this.read(izq,1); Pagina root = newPagina(this.orden,izq.getClaveOculta(),(int)this.add(izq),(int)sobre); this.write(root,1); } } } Árbol B+: El proceso de inserción en árboles-B+ es relativamente simple, similar al proceso de inserción en árboles-B. La dificultad se presenta cuando desea insertarse una clave en una página que se encuentra llena (m = 2d). En este caso, la página afectada se divide en 2, distribuyéndose las m + 1 claves de la siguiente forma: " las d primeras claves en la página de la izquierda y las d + 1 restantes claves en la página derecha”. Una copia de la clave del medio sube a la página antecesora. En la figura 8.5 hay dos diagramas que ilustran como funciona este caso.
Puede suceder que la página antecesora se desborde nuevamente, entonces tendrá que repetirse el proceso anterior. Es importante notar que el desbordamiento en una página que no es hoja no produce duplicidad de claves. El proceso de propagación puede llegar hasta la raíz, en cuyo caso la altura del árbol puede incrementarse en una unidad. En la figura 8.6 se presentan dos diagramas que clarifican y resuelven este caso.
10
Implementación en Java: public void insertar(int iElemento){ if(nodoRaiz == null) //Árbol vacío nodoRaiz = new NodoArbolBinario(iElemento); else nodoRaiz.insertar(iElemento); } public synchronized void insertar(int iElemento){ if(iElemento < dato ) {//Insertar en subárbol izquierdo //Insertar nuevo NodoArbolBinario if(nodoIzquierdo == null) nodoIzquierdo = new NodoArbolBinario(iElemento); else //Continuar recorriendo subárbol izquierdo nodoIzquierdo.insertar(iElemento); }else if(iElemento > dato){//Insertar en subárbol derecho //Insertar nuevo NodoArbolBinario if(nodoDerecho == null) nodoDerecho = new NodoArbolBinario( iElemento ); else //Continuar recorriendo subárbol derecho nodoDerecho.insertar(iElemento); } } } 11
Eliminaciones Árbol B: La eliminación de un elemento se puede realizar de dos formas: 1. Buscar y eliminar el elemento. 2. Recorrer el árbol y cada vez que encuentre al nodo que se va a eliminar se reestructure, para que no haiga que seguir reestructurándolo La Eliminación de un nodo hoja es parecida debido a que se busca el valor a eliminar, solo que al momento de la eliminación se borra la clave. En el caso de que sea un nodo interno se hace la distribución de los nodos restantes de forma tal que se cumpla el balanceo. Implementación en java: /** * Borra un clave del arbol B. * @param clave Clave a borrar. * @throws IOException * @throws ClassNotFoundException */ public void borrar(Clave clave) throws IOException, ClassNotFoundException { if (!this.vacio()) { Clave aux = this.Mm(clave,1,-1,false); if (aux!=null) clave = aux; this.borrar(clave,1,-1); // 1 es la posicion de la pagina raiz Pagina p = new Pagina(this.orden); this.read(p,1); if (p.getNumClaves()==0) if (p.getDesc(0)==-1) this.remove(1); else { int pos = p.getDesc(0); this.read(p,pos); this.write(p,1); this.remove(pos); } } }
Árbol B+:
12
La operación de borrado en árboles-B+ es más simple que la operación de borrado en árboles-B. Esto ocurre porque las claves a eliminar siempre se encuentran en las páginas hojas. En general deben distinguirse los siguientes casos: 1. Si al eliminar una clave, m queda mayor o igual a d entonces termina la operación de borrado. Las claves de las páginas raíz o internas no se modifican por más que sean una copia de la clave eliminada en las hojas.
2. Si al eliminar una clave, m queda menor a d entonces debe realizarse una redistribución de claves, tanto en el índice como en las páginas hojas.
13
Implementación en Java: public void eliminar(int iElemento){ nodoRaiz = eliminar(iElemento, nodoRaiz); } public NodoArbolBinario eliminar(int iElemento, NodoArbolBinario nodo){ if(nodo == null){ System.out.println(iElemento+" no encontrado"); return null; } if(iElemento < nodo.dato) nodo.nodoIzquierdo = eliminar(iElemento, nodo.nodoIzquierdo); else if(iElemento > nodo.dato) nodo.nodoDerecho = eliminar(iElemento, nodo.nodoDerecho); else if(nodo.nodoIzquierdo != null && nodo.nodoDerecho != null){ //Dos hijos nodo.dato = nodoMin(nodo.nodoDerecho).dato; nodo.nodoDerecho = eliminarMin(nodo.nodoDerecho); }else{ //Un hijo if(nodo.nodoIzquierdo != null) nodo = nodo.nodoIzquierdo; else nodo = nodo.nodoDerecho; } return nodo; } private NodoArbolBinario eliminarMin(NodoArbolBinario nodo){ if(nodo == null) return null; if(nodo.nodoIzquierdo != null) nodo.nodoIzquierdo = eliminarMin(nodo.nodoIzquierdo); else //No hay nodo izquierdo, el padre será el nodo derecho nodo = nodo.nodoDerecho; return nodo; }
14
Diferencias entre árboles B y B+
Un árbol B es un árbol binario, es decir, de cada nodo sólo pueden partir como máximo dos nodos. En enlace de los nodos se hace a través de la estructura jerárquica, es decir, cada nodo sólo sabe quién es su padre y sus hijos. Mientras que un árbol B+ es un árbol B (se cumple todo lo que he dicho anteriormente) pero además los nodos tienen un enlace a los elementos de su mismo nivel. Es decir, cada nodo sabe quién es su padre, su hijo izquierdo, su hijo derecho, si hermano izquierdo y su hermano derecho.
15
Conclusión
El futuro ingeniero de sistemas debe estar preparado y tener el conocimiento necesario sobre cómo se comportan los arboles B y B+ para afrontarlos de una manera eficaz, Teniendo en cuenta los diferentes métodos que se han descrito en el trabajo a presentar, para que sean usados en pro del desarrollo y solución de problemas.
16
Bibliografía
http://es.wikipedia.org/wiki/%C3%81rbol-B
http://fibonaccidavinci.wordpress.com/2010/01/10/arbol-b-en-java/ http://estructuradedatos-grupo1.blogspot.com/2009/04/arboles-b.html http://www.virtual.unal.edu.co/cursos/ingenieria/2001412/capitulos/cap8/85.html
http://es.wikipedia.org/wiki/%C3%81rbol_B%2B
17