CONTENIDO DE LA LECCIÓN 18
CONTENIDO DE LA LECCIÓN 18 CONTENIDO DE LA LECCIÓN 18
MIGUEL Á. TOLEDO MARTÍNEZ PLANEACIÓN DE LA SOLUCIÓN La búsqueda binaria representa una operación recursiva natural. Recuerde que la idea detrás de la recursividad es dividir un problema en subproblemas. Dividir un problema en subproblemas más simples de exactamente el mismo tipo hasta que ocurra una condición primitiva. Esto no es lo mismo que el diseño de software descendente, que divide los problemas en subproblemas más simples. La diferencia con la recursividad es que los subproblemas son exactamente del mismo tipo de problema que el problema original. Por ejemplo, suponga que está buscando un nombre en un directorio. Imagine que empieza al principio del directorio y ve cada nombre hasta que encuentra el correcto. Esto es exactamente lo que hace la búsqueda secuencial. ¿No sería más rápido, en promedio, abrir el directorio a la mitad? Después, determinar qué mitad del directorio contiene el nombre que está buscando, dividir esta sección del directorio a la mitad y así sucesivamente, hasta que obtiene la página en la cual aparece el nombre deseado. Aquí está un algoritmo que describe la búsqueda en el directorio como se describió. UN ALGORITMO DE BÚSQUEDA RECURSIVA EN UN DIRECTORIO buscaTel() INICIO si(el directorio telefónico sólo tiene una página) entonces Busca el nombre en la página. sino Abre el libro a la mitad. si(el nombre está en la primera mitad) entonces buscaTel(primera mitad del directorio para el nombre) sino buscaTel(segunda mitad del directorio para el nombre) FIN. ¿Observa cómo esta búsqueda es recursiva? Se mantiene realizando las mismas operaciones básicas hasta que llega a la página que contiene el nombre que está buscando. En otras palabras, la función buscaTel() se mantiene llamándose a sí misma en el enunciado anidado si/sino hasta que se encuentra la página correcta. La razón por la que se llama al proceso de búsqueda binaria es que deberá dividir el directorio entre 2 (bi) cada vez que se llama a sí mismo el algoritmo. Ahora, vamos a ver cómo se puede aplicar este proceso a la búsqueda en un arreglo de enteros. Se llamará a la función de búsqueda binaria recursiva busquedaBin() y se desarrollará el algoritmo en varios pasos. Aquí esta el primer nivel del algoritmo. Algoritmo busquedaBin(): Primer nivel busquedaBin() INICIO si(el arreglo tiene sólo un elemento) entonces Determine si este elemento es el elemento buscado. sino Encuentre el punto medio del arreglo. si(el elemento está en la primera mitad) entonces busquedaBin(primera mitad) sino busquedaBin(segunda mitad) FIN. Observe cómo este algoritmo es casi idéntico al algoritmo buscaTel() Aquí el proceso de búsqueda se continúa hasta que el arreglo se reduce a un elemento que se verifica contra el elemento que se está buscando. ¿Observa cómo la búsqueda se mantiene llamándose a sí misma hasta que ocurre la condición primitiva? Aunque este algoritmo proporciona una idea general de búsqueda binaria, se necesita mayor detalle para codificar el algoritmo. Para hacerlo, debemos preguntarnos que datos necesita busquedaBin() para realizar esta tarea. Bueno, al igual que la búsqueda secuencial, ésta necesita un arreglo en dónde buscar y el elemento que se va a buscar ¿correcto? Sin embargo, la búsqueda secuencial trata con ARREGLOS, APUNTADORES Y ESTRUCTURAS – LECCIÓN 18 18-52
MIGUEL Á. TOLEDO MARTÍNEZ un tamaño de arreglo dado, mientras que la búsqueda binaria necesita tratar con arreglos de tamaños diferentes conforme sigue dividiendo al arreglo original a la mitad. No solamente son estos arreglos de diferente tamaño, sino el primero y el último índices de cada mitad son diferentes. Como resultado, debemos proporcionar a busquedaBin() los límites del arreglo que está tratando en cualquier momento dado. Esto se puede hacer pasando el primero y último índices del arreglo dado a la función. Llamemos a estos índices primero y ultimo. Estamos listos para escribir la descripción de la interfaz de la función: Función busquedaBin(): Busca en un arreglo de enteros ordenado un valor determinado. Acepta: Un arreglo de enteros, un elemento de búsqueda, el primero y el último índices del arreglo en el cual se busca. Regresa: El índice del elemento, si se encuentra, o el valor -1 si el elemento no se encuentra. Esta descripción da suficiente información para escribir la interfaz de la función C++, como sigue: int busquedaBin(int A[], int elemento, int primero, int ultimo) Aquí, busquedaBin() regresará un valor entero que representa el índice del elemento que se busca. De nuevo, verá que regresará el valor -1 si el elemento no se encuentra en el arreglo. La función recibe el arreglo de enteros que se busca (A[]), el elemento que se busca (elemento), el primer índice del arreglo (primero) y el último índice del arreglo (ultimo) Observe que ningún tamaño se proporciona para el arreglo en que se busca porque la función buscará en forma recursiva en arreglos de diferentes tamaños. El siguiente problema es determinar qué valor de primero y ultimo se utilizarán para cualquier arreglo durante la búsqueda. Bueno, recuerde que se deberá dividir cualquier arreglo dado a la mitad para producir dos nuevos arreglos cada vez que se hace una llamada recursiva busquedaBin() Dado cualquier arreglo donde el primer índice es primero y el último índice es ultimo, se puede determinar el índice medio, como sigue: mitad = (primero + ultimo) / 2 Con este cálculo, la primera mitad del arreglo empieza en primero y finaliza en mitad - 1, y la segunda mitad del arreglo empieza en mitad + 1 y finaliza en ultimo. Esta idea se muestra en la figura 18.4. Pero, observe que ninguna mitad del arreglo contiene el elemento medio. Por me- dio de la utilización de esta técnica, las dos mitades no hacen un todo, ¿correcto? Por lo tanto, antes que se haga la división, suponga que verificamos el elemento medio para ver si es el elemento que se está buscando. La siguiente verificación realiza el trabajo. si (A[mitad] == elemento) entonces regresar mitad. Si esta verificación es verdadera antes de la división, se habrá encontrado el elemento que se está buscando y es posible terminar las llamadas recursivas. De otra manera, el elemento almacenado en A[mitad] no es el elemento que se está buscando, y esta posición del arreglo se puede ignorar durante el resto de la búsqueda. Si éste es el caso, se dividirá el arreglo y continuará el proceso recursivo. Sin embargo, se tiene que adicionar una segunda condición primitiva para el algoritmo recursivo. Aquí están las dos condiciones primitivas que se han hecho: 1. El arreglo que se busca tiene sólo un elemento. 2. A [mitad] == elemento. ARREGLOS, APUNTADORES Y ESTRUCTURAS – LECCIÓN 18 18-53
- Page 1 and 2: MIGUEL Á. TOLEDO MARTÍNEZ CONTENI
- Page 3 and 4: MIGUEL Á. TOLEDO MARTÍNEZ LECCIÓ
- Page 5 and 6: MIGUEL Á. TOLEDO MARTÍNEZ ELEMENT
- Page 7 and 8: MIGUEL Á. TOLEDO MARTÍNEZ Con las
- Page 9 and 10: MIGUEL Á. TOLEDO MARTÍNEZ del arr
- Page 11 and 12: MIGUEL Á. TOLEDO MARTÍNEZ // MUES
- Page 13 and 14: MIGUEL Á. TOLEDO MARTÍNEZ que exp
- Page 15 and 16: MIGUEL Á. TOLEDO MARTÍNEZ Ejemplo
- Page 17 and 18: MIGUEL Á. TOLEDO MARTÍNEZ Ejemplo
- Page 19 and 20: MIGUEL Á. TOLEDO MARTÍNEZ void ma
- Page 21 and 22: MIGUEL Á. TOLEDO MARTÍNEZ PASO DE
- Page 23 and 24: MIGUEL Á. TOLEDO MARTÍNEZ void pa
- Page 25 and 26: MIGUEL Á. TOLEDO MARTÍNEZ Ejemplo
- Page 27 and 28: MIGUEL Á. TOLEDO MARTÍNEZ int bus
- Page 29 and 30: MIGUEL Á. TOLEDO MARTÍNEZ El cuer
- Page 31 and 32: MIGUEL Á. TOLEDO MARTÍNEZ /******
- Page 33 and 34: MIGUEL Á. TOLEDO MARTÍNEZ Ejemplo
- Page 35 and 36: MIGUEL Á. TOLEDO MARTÍNEZ Ejemplo
- Page 37 and 38: MIGUEL Á. TOLEDO MARTÍNEZ /* El s
- Page 39 and 40: MIGUEL Á. TOLEDO MARTÍNEZ escribi
- Page 41 and 42: MIGUEL Á. TOLEDO MARTÍNEZ /* El s
- Page 43 and 44: MIGUEL Á. TOLEDO MARTÍNEZ Ejemplo
- Page 45 and 46: MIGUEL Á. TOLEDO MARTÍNEZ SOLUCI
- Page 47 and 48: MIGUEL Á. TOLEDO MARTÍNEZ // Busc
- Page 49 and 50: MIGUEL Á. TOLEDO MARTÍNEZ Paso 1
- Page 51: MIGUEL Á. TOLEDO MARTÍNEZ { j = i
- Page 55 and 56: MIGUEL Á. TOLEDO MARTÍNEZ necesit
- Page 57 and 58: MIGUEL Á. TOLEDO MARTÍNEZ { for (
- Page 59 and 60: MIGUEL Á. TOLEDO MARTÍNEZ // Comp
- Page 61 and 62: MIGUEL Á. TOLEDO MARTÍNEZ INICIAC
- Page 63 and 64: MIGUEL Á. TOLEDO MARTÍNEZ Esta ve
- Page 65 and 66: MIGUEL Á. TOLEDO MARTÍNEZ • Los
- Page 67 and 68: MIGUEL Á. TOLEDO MARTÍNEZ Es posi
- Page 69 and 70: MIGUEL Á. TOLEDO MARTÍNEZ p[100];
- Page 71 and 72: MIGUEL Á. TOLEDO MARTÍNEZ a) Cree
- Page 73 and 74: MIGUEL Á. TOLEDO MARTÍNEZ d) ¿cu
- Page 75 and 76: MIGUEL Á. TOLEDO MARTÍNEZ medio d
- Page 77 and 78: MIGUEL Á. TOLEDO MARTÍNEZ EXAMEN
MIGUEL Á. TOLEDO MARTÍNEZ<br />
un tamaño de arreglo dado, mientras que la búsqueda binaria necesita tratar con arreglos de tamaños<br />
diferentes conforme sigue dividiendo al arreglo original a la mitad. No solamente son estos arreglos de<br />
diferente tamaño, sino el primero y el último índices de cada mitad son diferentes. Como resultado,<br />
debemos proporcionar a busquedaBin() los límites del arreglo que está tratando en cualquier momento<br />
dado. Esto se puede hacer pasando el primero y último índices del arreglo dado a la función. Llamemos a<br />
estos índices primero y ultimo.<br />
Estamos listos para escribir la descripción de la interfaz de la función:<br />
Función busquedaBin(): Busca en un arreglo de enteros ordenado un valor<br />
determinado.<br />
Acepta: Un arreglo de enteros, un elemento de búsqueda, el primero<br />
y el último índices del arreglo en el cual se busca.<br />
Regresa: El índice del elemento, si se encuentra, o el valor -1 si el<br />
elemento no se encuentra.<br />
Esta descripción da suficiente información para escribir la interfaz de la función C++, como sigue:<br />
int busquedaBin(int A[], int elemento, int primero, int ultimo)<br />
Aquí, busquedaBin() regresará un valor entero que representa el índice del elemento que se busca. De<br />
nuevo, verá que regresará el valor -1 si el elemento no se encuentra en el arreglo. La función recibe el<br />
arreglo de enteros que se busca (A[]), el elemento que se busca (elemento), el primer índice del arreglo<br />
(primero) y el último índice del arreglo (ultimo) Observe que ningún tamaño se proporciona para el arreglo<br />
en que se busca porque la función buscará en forma recursiva en arreglos de diferentes tamaños.<br />
El siguiente problema es determinar qué valor de primero y ultimo se utilizarán para cualquier arreglo<br />
durante la búsqueda. Bueno, recuerde que se deberá dividir cualquier arreglo dado a la mitad para producir<br />
dos nuevos arreglos cada vez que se hace una llamada recursiva busquedaBin() Dado cualquier arreglo<br />
donde el primer índice es primero y el último índice es ultimo, se puede determinar el índice medio, como<br />
sigue:<br />
mitad = (primero + ultimo) / 2<br />
Con este cálculo, la primera mitad del arreglo empieza en primero y finaliza en mitad - 1, y la segunda<br />
mitad del arreglo empieza en mitad + 1 y finaliza en ultimo. Esta idea se muestra en la figura <strong>18</strong>.4.<br />
Pero, observe que ninguna mitad del arreglo contiene el elemento medio. Por me- dio de la utilización de<br />
esta técnica, las dos mitades no hacen un todo, ¿correcto? Por lo tanto, antes que se haga la división,<br />
suponga que verificamos el elemento medio para ver si es el elemento que se está buscando. La siguiente<br />
verificación realiza el trabajo.<br />
si (A[mitad] == elemento) entonces<br />
regresar mitad.<br />
Si esta verificación es verdadera antes de la división, se habrá encontrado el elemento que se está buscando<br />
y es posible terminar las llamadas recursivas. De otra manera, el elemento almacenado en A[mitad] no es el<br />
elemento que se está buscando, y esta posición del arreglo se puede ignorar durante el resto de la búsqueda.<br />
Si éste es el caso, se dividirá el arreglo y continuará el proceso recursivo. Sin embargo, se tiene que<br />
adicionar una segunda condición primitiva para el algoritmo recursivo. Aquí están las dos condiciones<br />
primitivas que se han hecho:<br />
1. El arreglo que se busca tiene sólo un elemento.<br />
2. A [mitad] == elemento.<br />
ARREGLOS, APUNTADORES Y ESTRUCTURAS – <strong>LECCIÓN</strong> <strong>18</strong> <strong>18</strong>-53