Está en la página 1de 14

Algoritmos de bsqueda.

Tal y como hicimos en la unidad pasada, es necesario comprender y empezar a utilizar los algoritmos de bsqueda de algn dato determinado. Como los algoritmos de ordenamiento, los algoritmos de bsqueda son procesos que por si solos permiten la ubicacin de informacin, o bien, fungen como procesos auxiliares para algoritmos o procesos ms complejos respecto a la identificacin de datos. 1.- Bsqueda sencuencial (lineal). Este algoritmo se basa en la premisa sencilla de ir buscando un dato en un conjunto de datos determinados, siendo uno de los algoritmos mucho ms sencillos de utilizar, y cuya lgica es primordial para procesos ms complejos de bsqueda de datos utilizando otros algoritmos para ello. Este algoritmo tiene algunas variantes, dependiendo del lenguaje de programacin donde se utilice, veamos primero, como poder implementarlo de manera formal, considerando nicamente los elementos ms sencillos de l mismo, considerando, que se tiene un vector de enteros de tamao T (constante), y que la variable tamano contiene el nmero de elementos que se tienen en dicho vector, y por ltimo, la variable valor contiene el valor que se est buscando:
int busquedaSecuencial(int vector[T],int tamano, int valor) { int contador; int posicion; contador=0; posicion=-1; while (contador<tamano) { if (vector[contador]==valor) {posicion=contador;} contador++; }//fin del while return (posicion); }//fin de la funcion

Observa como de manera inicial, estamos inicializando la variable posicion con un menos uno 1, indicando con esto que si se tiene al final del recorrido el valor de -1 el dato no fue encontrado, regresndolo a travs de la funcin. Caso contrario, si el valor es encontrado (mediante la comparacin) se regresa un valor diferente de -1 dando con esto por hecho de que si se ha encontrado el valor en el vector, y dicha posicin ser regresada para su posterior utilizacin. Este algoritmo por si mismo aunque funciona, no es eficiente, pues aunque se haya encontrado el valor en el vector seguir recorriendo todas y cada una de las posiciones, resultando en un tiempo excesivo (imagnate, que tuvieras un vector de 1,000,000 de posiciones, y tu dato est en la segunda posicin, ejecutaras el resto de las comparaciones aunque el dato ya se hubiera encontrado). Dependiendo del lenguaje de programacin, podemos hacer una modificacin al mismo para interrumpir el flujo del programa, y con ello ahorrarnos el resto de las comparaciones, resultando en una mejora de eficiencia del tiempo. El cdigo sera el siguiente:

int busquedaSecuencial(int vector[T],int tamano, int valor) { int contador; int posicion; contador=0; posicion=-1; while (contador<tamano) { if (vector[contador]==valor) { posicion=contador; break; } contador++; }//fin del while return (posicion); }//fin de la funcion

Observa como la nica variante sucede en caso de que el valor haya sido encontrado en el vector, resultando en la sentencia break, la cual permite terminar el flujo de la estructura while y con ello, ahorrarnos todas las comparaciones restantes (junto con los ciclos indicados), pero, a algunos puristas de la programacin esto no les parece, pues se rompe con el flujo del programa, es por ello, que se propone otra solucin (otra variante del cdigo), como se indica a continuacin:
int busquedaSecuencial(int vector[T],int tamano, int valor) { int contador; int posicion; contador=0; posicion=-1; while (contador<tamano) { if (vector[contador]==valor) { posicion=contador; return (posicion); } contador++; }//fin del while return (posicion); }//fin de la funcion

Observa como aqu en lugar de un break estamos utilizando un return. En Lenguaje C la sentencia return indica que se regresar un valor, y por ello, es lo ltimo que se ejecuta de cualquier funcin, esto quiere decir que cualquier lnea de cdigo que pongas despus de la sentencia return no ser ejecutado, pues se finaliza la funcin por si misma. Otra variante (que implica el uso de otra variable) es la que se indica a continuacin, la cual permite mantener la estructura bsica del ciclo, de las comparaciones, pero, tambin finaliza el ciclo en caso de que se encuentren condiciones innecesarias. Observa el siguiente cdigo:
int busquedaSecuencial(int vector[T],int tamano, int valor) { int contador; int posicion; char encontrado;

contador=0; posicion=-1; encontrado='0'; while ((contador<tamano)&&(encontrado=='0')) { if (vector[contador]==valor) { posicion=contador; encontrado='1'; } contador++; }//fin del while return (posicion); }//fin de la funcion

La nica inclusin es la de una variable de tipo carcter (encontrado), la cual tiene un valor inicial que permite la entrada al ciclo, en caso de que se encuentre el valor en el vector, cambia su valor y por lo tanto rompera el flujo de la estructura iterativa, resultando con el regreso de la posicin donde se encontr el valor. Como puedes ver este algoritmo por si solo resulta sumamente til, siempre y cuando se considere la insercin de estructuras que impida la ejecucin de ciclos innecesarios. 2.- Bsqueda binaria. Antes de empezar con estos algoritmos es conveniente indicar lo siguiente (y se har con letras maysculas, pues es indispensable indicarlo): ESTOS ALGORITMOS DE BSQUEDA NO FUNCIONAN CORRECTAMENTE SI LOS DATOS EN EL VECTOR NO ESTN ORDENADOS. Se comenta lo anterior, pues, se desconoce cual ser el comportamiento de estos algoritmos con una lista desordenada, ya que se basan en el principio del orden para poder dividir la informacin. El algoritmo de bsqueda binaria est basado en la filosofa de programacin divide y vencers los cuales implican que el problema original sea dividido en problemas ms pequeos, donde cada uno de stos sub-problemas se estudia y se vuelve a dividir si es necesario. La idea es construir una estrategia que te lleve hacia la respuesta del problema de una manera eficiente. El enfoque divide y vencers aplica una tcnica de divisin de un problema central en varios subproblemas (generalmente dos), si la solucin de los sub-problemas se puede obtener de manera directa, la solucin al problema central se obtiene mediante la combinacin de las soluciones. Pero, si los sub-problemas siguen siendo muy grandes, se pueden an dividir en sub-problemas. Lo que se hace es dividir en sub-problemas de forma continua, utilizando la recursividad hasta que el subproblema que se obtiene sea lo suficientemente pequeo para que se pueda resolver de manera directa. Este enfoque, el de divide y vencers, es un enfoque top-down, donde, la solucin de un nivel superior (top-level) se obtiene yendo hacia abajo y obteniendo soluciones a los sub-problemas. Un algoritmo del tipo divide y vencers convencional es el de la bsqueda binaria, donde, retomaremos un ejercicio tradicional de este tipo de algoritmos, el cual se explica a continuacin: Imagnate que deseas encontrar el nmero telefnico de algn amigo en el directorio. El nico dato

que tienes es el nombre de tu amigo, y el directorio est ordenado de manera alfabtica. A continuacin, una forma esencial para encontrar el telfono sera la siguiente: Compara la primera entrada del directorio con el nombre, si son iguales, ya acabaste. Si no, compara la segunda entrada del directorio con el nombre, si son iguales, acabaste. Si no, compara la tercera entrada del directorio con el nombre......... Este procedimiento funcionara de manera ideal si el directorio tuviera pocas entradas, pero provoca ciertos detalles si el directorio tuviera muchas entradas, ya que ralentizara la eficiencia de la bsqueda. La solucin propuesta es la siguiente: Abre el directorio a la mitad y compara la entrada que observes con el nombre de tu amigo. Si son iguales, ya finaliza el proceso de bsqueda. Si no son iguales, entonces: El nobmre est antes del que viste, o est despus. Continuars buscando en la mitad que se supone debe de estar. Repites el procedimiento de divisin del directorio.

Has dividido la tarea en dons, por ello, el mtodo contina de la misma forma con la mitad restante, hasta que finalmente obtengas una seccin del directorio que contiene nicamente una sola entrada, que debe corresponder con la del nombre de tu amigo. Ahora, analizaremos el pseudocdigo, mediante la utilizacin de una funcin, donde, tendremos los siguientes elementos: N.- Cantidad de nmeros de un arreglo. L1, L2, L3, .... .- Miemtros de la lista (de tamao N). x.- El nmero que se est buscando. izq.- ndice izquierdo de la lista. der.- ndice derecho de la lista. med.- Punto medio de la parte de la lista. De manera inicial consideraremos que izq=1 y der=N. Ahora, veamos el algoritmo:
funcin binaria (izq, der) si (izq<der) entonces med=(izq+der)/2 si (L(med)<x) entonces binaria(med,der) si no si (L(med)==x) entonces binaria(med,x) si no binaria(izq,med) Fin si si no entonces si (L(izq)==x) Escribir Encontrado en la posicion + izq si no Escribir El elemento buscado no est en el directorio Fin si Fin funcion binaria

Para poder resolver este algoritmo es necesario que comprendas el concepto de recursividad, pues, es precisamente lo que hace referencia sobre su operacin (la invocacin de un procedimiento o funcin cierto nmero de veces hasta que se encuentre el resultado deseado). Veamos ahora una

breve corrida de escritorio con este algoritmo:


x=4 N=10 izq=1 der=10 (N) L(N) = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Operacin izq<der? med=(izq+der)/2 L(med)<x? binaria(izq,med) izq<der? med=(izq+der)/2 L(med)<x? L(med)==x? binaria(med,x) izq<der? L(izq)==x? Sustitucin 1<10? Med=(1+10)/2 L(6)<4? Binaria(1,6) 1<6? Med=(1+6)/2 L(4)<4? L(4)==4? Binaria(4,4) 4<4? L(4)==4? False True 4 Escribe 4 4 True 4 False True 4 4 4 4 1 1 1 1 6 6 6 6 4 4 4 Resultado True 6 False X 4 4 4 Izq 1 1 1 Der 10 10 10 6 6 Med

Veamos otra ubicacin:


x=9 N=10 izq=1 der=10 (N) L(N) = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Operacin izq<der? med=(izq+der)/2 L(med)<x? binaria(med,der) izq<der? med=(izq+der)/2 L(med)<x? binaria(med,der) izq<der? med=(izq+der)/2 L(med)<x? L(med)==x? binaria(med,x) izq<der? Sustitucin 1<10? Med=(1+10)/2 L(6)<9? Binaria(6,10) 6<10? Med=(6+10)/2 L(8)<9? Binaria(8,10) 8<10? Med=(8+10)/2 L(9)<9? L(9)==9? Binaria(9,9) 9<9? False True 9 False True True 8 True Resultado True 6 True X 9 9 9 9 9 9 9 9 9 9 9 9 9 9 Izq 1 1 1 1 6 6 6 6 8 8 8 8 8 9 Der 10 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 8 8 8 6 6 6 Med

L(izq)==x? Escribir

L(9)==9?

True

Ahora, una codificacin directa del algoritmo de bsqueda binaria, pero, sin la utilizacin de recursividad sera la siguiente (considerando un vector, un tamao del vector y el valor que se est buscando):
int busquedaBinaria(int vector[T], int tamano, int valor) { int inferior=0; int superior=tamano-1; int medio; int resultado=-1; while ((resultado<0) && (inferior<=superior)) { medio=(inferior+superior)/2; if (vector[medio]==valor) { resultado=medio; } else { if (valor<vector[medio]) { superior=medio-1; } else { inferior=medio+1; } }//fin del else }//fin del while return (resultado); }//fin de la funcion

Observa como mediante la estructura iterativa (el ciclo while) es como estamos reduciendo el vector a mitades, buscando el dato en cada una de las posiciones. De forma inicial, resultado vale -1 indicando con esto que el dato no ha sido encontrado (por ello la comparacin de resultado<0). Cuando se encuentra el valor en alguna de las mitades, entonces el resultado cambia su valor, y regresar la posicin de dnde est ubicado el dato en un determinado vector. Tambin, si la posicin menor es mayor que la posicin mayor entonces el ciclo termina, indicando con esto que el dato no ha sido encontrado y regresando un -1 (falso, no se encontr el dato). Otra variacin del algoritmo, directamente sobre el cdigo, es la siguiente (pero, incluyendo recursividad):
int busquedaBinaria(int vector[T], int valor, int mayor, int menor, int resultado) { int medio; if (menor>mayor) { resultado=-1; }

else { if (resultado==-1) { medio=(menor+mayor)/2; if (vector[medio]==valor) { resultado=medio; } else { if (valor<vector[medio]) { mayor=medio-1; resultad=busquedaBinari(vecto,valo,mayo,meno,resultad); } else { menor=medio+1; resultad=busquedaBinari(vecto,valor,mayor,menor,resultado); } }//fin del else }//fin del if }//fin del else superior return (resultado); }

De manera inicial se le pasa a la funcin los valores del vector, el valor que se est buscando, la posicin mayor (que es el tamao-1), la posicin menor (que de manera inicial es cero 0) y el resultado (que igual, nuevamente es un -1 indicando que es falso). Se hacen las mismas comparaciones que en el cdigo iterativo, pero aqu existe una diferencia, pues cada vez que el dato no se encuentra y se divide el vector a la mitad, se vuelve a llamar a la funcin, pero, ahora, con los parmetros correspondientes de la mitad del vector (lo mismo que hacamos anteriormente, pero ahora simulando que enviamos un vector ms pequeo). El resultado es exactamente el mismo, salvo que esta funcin ocupa la tcnica de recursividad para la invocacin de sus parmetros, y, con ello, se optimizan los procesos de memoria en la compilacin. 3.- Bsqueda en rboles. Para la utilizacin de estos algoritmos, es necesario antes que nada definir conceptos bsicos sobre los rboles (a nivel de estructura de datos) los cuales se vern muy ligeramente, pues en la materia anterior de estructura de datos tuviste que haber aprendido a programarlos y gestionar cada uno de sus elementos. Tcnicamente un rbol es una estructura de datos, la cual se debe de manipular de forma recursiva (es decir, reinvocacin de cada una de las funciones que lo componen, dependiendo de las operaciones que se desean realizar con l), el cual es considerado como un grafo, siendo bsicamente un grafo no dirigido mediante el cual puede existir un desplazamiento a travs del rbol.

Figura 1. Grafo que contiene letras como ubicacin de elementos. Ser llamado Grafo 1.

Figura 2. Grafo ubicado mediante la consideracin de valores binarios. Ser llamado Grafo 2.

Figura 3. Grafo ligeramente balanceado sobre sus elementos. Ser llamado Grafo 3.

Figura 4. Grafo identificado con valores numricos en su interior. Ser llamado Grafo 4. Para usos prcticos en la programacin, y para poder buscar algn elemento al interior de un rbol, es necesario especificar que se necesita un rbol binario, el cual contiene las siguientes caractersticas: El nodo inicial (raz) contiene un valor determinado. Si el prximo valor a insertar es mayor que el nodo, se ubica a la derecha del mismo. Si el prximo valor es menor que el nodo raz se ubica a la izquierda del mismo. Si existen ms valores a insertar, se van ubicando, ya sea a la derecha o a la izquierda del nodo que se aproxime ms a su valor.Observa las figuras anteriores, (figura 2, 3 y 4) las cuales representan la ubicacin de un rbol binario (observa como los valores se van acomodando dependiendo de la ubicacin de los nodos).

A nivel de programacin, un rbol binario es una estructura (apuntador a estructura) la cual contiene en su interior dos apuntadores, uno hacia la izquierda y otro hacia la derecha. Al igual que con las listas ligadas, una raz vaca (rbol vaco) se considera con valor de NULL. La declaracin se hace de la siguiente forma:
struct estructura { int valor; struct estructura *izquierda; struct estructura *derecha; }; typedef struct estructura tree;

Observa como no es nada del otro mundo, salvo lo que ya hemos realizado, la declaracin de una estructura (como si fuera una lista doblemente ligada), con esto generaramos el rbol que vamos a ocupar para el resto de los ejercicios. La nica lnea que no has manejado todava es el typedef, lo cual hace que el texto struct estructura ahora sea llamado tree, esto con la finalidad de ahorrar lneas de cdigo ms adelante. Para insertar valores dentro del rbol, es necesario utilizar una funcin, la cual ocupa el apuntador que hayamos definido de tipo tree (recuerda el typedef):
void insertarValor(tree **arbol, int valor) { if (*arbol==NULL) { *arbol=(tree *)malloc(sizeof(tree)); (*arbol)->valor=valor;

(*arbol)->izquierda=NULL; (*arbol)->derecha=NULL; } else if ((*arbol)->valor < valor) { insertarValor(&(*arbol)->derecha,valor); } else if ((*arbol)->valor > valor) { insertarValor(&(*arbol)->izquierda,valor); } }//fin de la funcion

Observa como hacemos lo mismo que con una lista doblemente ligada, el reservar la memoria si todava no ha sido reservada (has de cuenta que tienes un nodo head vaco, por lo tanto vale nulo). En caso de que no est vaco el rbol, se pregunta si los valores son mayores o menores, ejecutando el proceso recursivo, y, con ello, avanzando a travs del rbol para ubicar el nuevo valor en el lugar que le corresponde. Al final, siempre ubica al nuevo nodo generado en su parte derecha e izquierda apuntando a NULL, indicando la finalizacin de la insercin del nodo. Para poder comprobar que has ingresado los valores en el rbol, es conveniente ejecutar los recorridos de los rboles, existiendo para ello tres en general: a).- Recorrido en pre-orden.- Visitar (imprimir) el nodo actual (la raz del rbol), para luego visitar los sub-rboles izquierdos, y una vez que se ha recorrido todo el sub-rbol izquierdo, se visita el sub-rbol derecho. El algoritmo de recorrido es el siguiente:
void recorridoPreorden (tree *arbol) { if (arbol!=NULL) { printf("\n%i",arbol->valor); recorridoPreorden(arbol->izquierda); recorridoPreorden(arbol->derecha); } }

Para el Grafo 1 su recorrido sera el siguiente: a, b, d, c, e, f Para el Grafo 2 su recorrido sera el siguiente: 10, 15, 20, 25, 30 Para el Grafo 3 su recorrido sera el siguiente: 50, 20, 10, 5, 25, 70, 60, 55, 65, 80 Para el Grafo 4 su recorrido sera el siguiente: 10, 6, 5, 7, 8, 12, 11, 13, 14 b).- Recorrido In-orden.- Se visita (imprime) el sub-rbol izquierdo, el nodo actual (raz del rbol) y despus se visita el rbol derecho. El algoritmo de recorrido es el siguiente:
void recorridoInorden (tree *arbol) { if (arbol!=NULL)

{ recorridoInorden(arbol->izquierda); printf("\n%i",arbol->valor); recorridoInorden(arbol->derecha); } }

Para el Grafo 1 su recorrido sera el siguiente: b, d, a, e, c, f Para el Grafo 2 su recorrido sera el siguiente: 10, 15, 20, 25, 30 Para el Grafo 3 su recorrido sera el siguiente: 5, 10, 20, 25, 50, 55, 60, 65, 70, 80 Para el Grafo 4 su recorrido sera el siguiente: 5, 6, 7, 8, 10, 11, 12, 13, 14 c.- Recorrido Post-orden.- En este recorrido primero se visita (imprime) el sub-rbol izquierdo, posteriormente, el sub-rbol derecho, y por ltimo, el nodo actual (raz del rbol). Su cdigo es el siguiente:
void recorridoPostorden (tree *arbol) { if (arbol!=NULL) { recorridoPostorden(arbol->izquierda); recorridoPostorden(arbol->derecha); printf("\n%i",arbol->valor); } }

Para el Grafo 1 su recorrido sera el siguiente: d, b, e, f, c, a Para el Grafo 2 su recorrido sera el siguiente: 30, 25, 20, 15, 10 Para el Grafo 3 su recorrido sera el siguiente: 5, 10, 25, 20, 55, 65, 60, 80, 70, 50 Para el Grafo 4 su recorrido sera el siguiente: 5, 8, 7, 6, 11, 14, 13, 12, 10 Para borrar el rbol en su totalidad debers ocupar el algoritmo de recorrido en Post-orden, pues de esta forma aseguras que no perders la ubicacin de las ramas del rbol en el recorrido, solamente que en lugar de imprimir, debers liberar la memoria del nodo (free). El cdigo sera el siguiente:
void borrarArbol (tree *arbol) { if (arbol!=NULL) { borrarArbol(arbol->izquierda); borrarArbol(arbol->derecha); free(arbol); } }

Por ltimo, y lo que nos concierne a los algoritmos de bsqueda, precisamente la bsqueda de un elemento determinado en un rbol binario, para indicar si se ha encontrado o no dicho valor dentro de el mismo rbol. El cdigo es el siguiente:
int buscarValor(tree *arbol, int buscado) { if (arbol==NULL) { return (0); } else if (buscado==arbol->valor) { return (1); } else if (arbol->valor<buscado) { return buscarValor(arbol->derecha,buscado);} else if (arbol->valor>buscado) { return buscarValor(arbol->izquierda,buscado); } else { return (1); } }//fin de la funcion

Observa como pasamos en si el rbol a la funcin, donde, si el rbol es NULL (es decir, nulo) quiere decir que todava no hay ningn elemento a buscar dentro del rbol, o bien, se finaliz el recorrido sin encontrar el valor (por lo tanto, se regresa un 0). Ahora, se efectan las comparaciones, donde, si el valor buscado ya se encontr en algn nodo, se regresa un 1 indicando que apareci el valor, ahora, se hacen comparaciones, donde, se avanza de manera recursiva hacia la izquierda y hacia la derecha. Se avanza hacia la izquierda del rbol si el valor que se est buscando es menor que donde se est ubicado en el rbol actualmente, y se avanza hacia la derecha del rbol si el valor que se est buscando es mayor que en el nodo donde se est ubicado en el rbol en estos momentos. 4.- Bsqueda en anchura. Retomando parte del material de los rboles binarios, es necesario identificar otro tipo de recorridos que se pueden hacer sobre el mismo, en funcin de la practicidad de la bsqueda de algn elemento o un determinado valor. No veremos en este material los algoritmos de bsqueda en profundidad, pues ya han sido vistos anteriormente (los conociste como recorridos preorden, inorden y postorden), sino ms bien la bsqueda en anchura. Como fue comentado anteriormente, un recorrido en profundidad incluye la bsqueda de informacin a travs del fondo del rbol binario (recorres nodos u hojas del rbol hacia adentro, o hacia afuera), pero, falta un tipo de bsqueda, la cual es conocida como bsqueda en anchura (o recorrido en anchura).

En este tipo de recorrido se visita un rbol por niveles, donde, se efectan los siguientes pasos: Se visitan los nodos del nivel 1 (la raz del rbol) Se visitan los nodos del siguiente nivel (nivel 2). Se visitan los nodos del siguiente nivel (nivel 3). Las consideraciones de la visita se hace de izquierda hacia derecha. Se visitan los niveles sub-secuentes hasta que ya no queden ms niveles.

Observa como cambia un poco el esquema, pues ahora el recorrido es a travs de los niveles del rbol, motivo por el cual este recorrido no se hace de forma recursiva, sino ms bien de manera iterativa. Es conveniente destacar que para este recorrido se utiliza una cola (recuerda estos elementos: El primero que entra es el primero que sale). El procedimiento bsico que se sigue para recorrer un rbol por anchura es el siguiente: Se encola (se guardan los elementos en una cola) si el rbol no est vaco. Los elementos que se guardan son los nodos del sub-rbol izquierdo y sub-rbol derecho del nodo extrado en la cola. Se sigue desencolando y encolando hasta que la cola este vaca. Para ello, considerando los cdigos anteriores de rboles binarios, veamos el cdigo para recorrer un rbol en anchura:
void recorridoAmplitud (tree *arbol) { int imprimir; tree *cola[100]; int tamano=0; //tamao de la cola tree *aux=arbol; int cont; if (arbol!=NULL) { cola[tamano]=aux; tamano++; while (tamano>0) { aux=cola[0]; printf("\n %i ",aux->valor); for (cont=0;cont<tamano-1;cont++) { cola[cont]=cola[cont+1]; } tamano--; if (aux->izquierda !=NULL) { cola[tamano]=aux->izquierda; tamano++; }//fin del if izquierda if (aux->derecha!=NULL) { cola[tamano]=aux->derecha; tamano++; }//fin del if derecha }//fin del while

}//fin del if }//fin de la funcion

Observa los siguientes elementos en el cdigo: Si el rbol es igual a NULL (nulo) quiere decir que es un rbol vaco y no se puede recorrer. Tenemos una cola (vector) de tipo * tree, pues en dicha cola iremos guardando los nodos del rbol (observa que tiene un tamao mximo, as que ten cuidado con eso). Como se coment en el procedimiento, es necesario encolar los nodos, por ello la definicin de la cola. Se guarda el noco raz del rbol en la cola y se incrementa el tamao. Se efectan ciclos hasta que ya no existan elementos en la cola. El proceso de desencolar implica el mover todos los elementos de la derecha del primero, y ubicarlos en su posicin izquierda (recuerda que en una cola el primero que sale fue el primero que entr, como en un super-mercado). Se va avanzando sobre los niveles del rbol almacenndo cada nodo en la cola, recuperndolo y siguiendo avanzando hasta que sea diferente de NULL el elemento izquierdo y derecho del nodo actual.