Suponiendo que deseamos encontrar la llave k, entonces el algoritmo inicia la búsqueda en el nodo raíz y compara todos los elementos llaves, en orden ascendente, con k hasta que encontremos una llave mayor o terminemos de comparar todas las llaves sin encontrar la llave mayor. Para esta tarea implantamos una funcón llamada node_search, la cual tiene 2 entradas: el nodo y k, y regresa el índice donde podría estar la llave, en realidad este número es el índice de la máxima llave menor o igual a k. Por ejemplo, si el nodo tuviese las llaves (5, 10, 12, 17, 20) y , entonces node_search nos indicaría que el tercer elemento (12) es la máxima llave menor o igual a 15, lo que establece que si el nodo es una rama es que posiblemente 15 se encuentre en el tercer subárbol hijo de nodo. En C esta función queda implantada como:
/* Regresa el menor entero j */ /* tal que k <= key(p,j) */ /* [ABRIL-97] */ /* AMILCAR MENESES VIVEROS */ int nodesearch(node *p, Bkey k) { int i; for (i=0; i < (p->nKeys); i++) if ( cmpkey(k,p,i) <= 0 ) return i; return i; }Esta función incluye, a su vez, a la función cmpkey(), que compara a la llave k, con el i-ésimo elemento del nodo p, si k es menor regresa -1, 0 si es igual y 1 si es mayor.
Retomando la filosofía de node_seach escribimos una función que se encarga de buscar, en el B+, la hoja y posición donde posiblemente se encuentre k, esto és, la posición correspondiente con la máxima llave menor o igual que k. Esto tiene sus ventajas para otras operaciones que se realizan en el árbol. Así, la función search_leaf tiene como valores de entrada el nodo donde se inicia la búsqueda, la llave k, y un apuntador a la posición en el nodo; y regresa el apuntador al nodo hoja donde debe estar k. Esta función opera de la siguiente forma: busca el índice i correspondiente a k en el nodo, una vez obtenido este valor, se pregunta si el nodo es una hoja, si lo és, entonces se coloca a i como valor de la posición y se regresa el apuntador de este nodo; en caso de ser una rama, entonces se regresa el valor de la misma función, pero ahora se inyecta el i-ésimo árbol-hijo como valor de entrada:
/* Busca la hoja y posicion donde se debe estar la llave k, */ /* regresa NULL si el arbol esta vacio */ /* [ABRIL-97] */ /* AMILCAR MENESES VIVEROS */ node *search_leaf(node *p, Bkey k, int *position) { int i; if (p==NULL) { *position = -1; return NULL; } i = nodesearch(p, k); if (isleaf(p)==BTRUE) { *position = i; return p; } return (search_leaf(p->an[i], k, position)); }
De esta forma cuando deseamos buscar un elemento en el árbol llamamos a la función search_leaf y comparamos que el valor del índice sea menor que el orden del árbol --esto se debe a que el arreglo de llaves tiene un elemento menos que el orden del árbol-- y comparamos a k con la i-ésima llave de la hoja encontrada.
void search(node *root, Bkey k) { node *ns; Bregister *r; int i; if ((ns=search_leaf(root,k,&i))==NULL) { printf("\n El elemento"); printf(FFkey,k); printf("no se encontro"); } else if ( i < (ORDER-1) && k == (ns->ak[i]) ) { r = ns->ap[i]; printf("\n Llave : "); printf(FFkey, PKeyNode(r)); printf("\n Nombre : %s", r->nombre); printf("\n Edad : %d", r->edad); } else printf("\n El elemento FKey no se encontro", k); printf("\n Presione cualquier tecla para continuar ..."); getchar(); }