# PR 4 [Volver a la página principal de "Fundamentos de la Programación"](../README.md) **Índice** - [PR 4](#pr-4) - [17. Esquemas de recorrido y búsqueda](#17-esquemas-de-recorrido-y-búsqueda) - [17.1. Aproximación intuitiva](#171-aproximación-intuitiva) - [17.1.1. Ejemplo 1 - Temperatura media](#1711-ejemplo-1---temperatura-media) - [17.1.2. Ejemplo 2 - Recaudaciones de una sala de cine](#1712-ejemplo-2---recaudaciones-de-una-sala-de-cine) - [17.2. Esquema de recorrido](#172-esquema-de-recorrido) - [17.3. Esquema de búsqueda](#173-esquema-de-búsqueda) - [17.3.1. Ejemplo](#1731-ejemplo) ## 17. Esquemas de recorrido y búsqueda Ya hemos visto las estructuras secuencial, alternatica e iterativa, con esto, ya podemos resolver cualquier problema. Ahora vamos a ver esquemas de recorrido y búsqueda, que son una especie de patrones o estructuras predeterminadas para diseñar algoritmos de manera más sistemática y ganar en eficiencia y fiabilidad. Un esquema es una especie de plantilla que nos permite solucionar un tipo de problema específico con adaptaciones a cada caso concreto. Un ejemplo de aplicación de esquemas de recorrido y búsqueda es para resolver problemas de tratamiento de secuencias de manera más eficiente y sistemática. ### 17.1. Aproximación intuitiva La idea es que, en lugar de ir a ciegas, sigamos un esquema de recorrido o búsqueda que nos permita ir avanzando de manera sistemática y eficiente. Por ejemplo, si tenemos que recorrer una matriz, podemos hacerlo por filas o por columnas, o si tenemos que buscar un elemento en una lista, podemos hacerlo de manera secuencial o binaria. #### 17.1.1. Ejemplo 1 - Temperatura media Vamos a calcular la temperatura media de todo el año suponiendo que vamos leyendo por el canal de entrada las temperaturas medias de cada día: ```alg algorithm averageTemp var temperature: real; average: real; i: integer; end var i:= 0; average:= 0; while i < 365 do temperature:= readReal(); average:= average + temperature; i:= i + 1; end while write(average / 365.0); end algorithm ``` ```c #include int main(int argc, char** argv) { float temperature; float average; int i; i = 0; average = 0; while (i < 365) { scanf("%f", &temperature); average = average + temperature; i = i + 1; } printf("%f\n", average / 365.0); return 0; } ``` #### 17.1.2. Ejemplo 2 - Recaudaciones de una sala de cine Cargamos los datos de una tabla de recaudaciones de una sala de cine a partir de lo leído por el canal de entrada estándar. ```alg const MAX_THEATERS: integer = 20; END_SEQ: real = -1.0; end const type tTheater = record collect: vector[MAX_THEATERS] real; numTheaters: integer; end record end type action fillTable(inout movieTheater:tTheater); var i: integer; temp: real; end var temp:= readReal(); {We read the first value} movieTheater.numTheaters:= 0; while temp ≠ END_SEQ do movieTheater.numTheaters:= movieTheater.numTheaters + 1; movieTheater.collect[movieTheater.numTheaters]:= temp; temp:= readReal(); end while end action ``` ```c #include #define END_SEQ -1 #define MAX_THEATERS 20 typedef struct { float collect[MAX_THEATERS]; int numTheaters; } tTheater; void fillTable(tTheater *movieTheater) { /* var definition */ int i; float temp; /* table initialization */ temp = 0; movieTheater->numTheaters = 0; scanf("%f", &temp); /* read the first value */ /* iteration while the read number is not -1 */ while (temp != END_SEQ) { /* Save the read number in the table */ movieTheater->collect[movieTheater->numTheaters] = temp; movieTheater->numTheaters = movieTheater->numTheaters + 1; scanf("%f", &temp); } } ``` ### 17.2. Esquema de recorrido En los dos ejemplos anteriores estamos haciendo un recorrido a través de una serie de datos repitiendo el mismo esquema: 1. Acceso al primer elemento. En el primer ejemplo, leemos el primer valor de la temperatura y en el segundo, leemos el primer valor de la tabla. 2. Tratamiento inicial. Inicializamos las variables que utilizaremos para hacer el tratamiento posterior. 3. Último elemento. Comprobamos si hemos llegado al último elemento. 4. Trater elemento. Aplicamos las acciones necesarias para resolver cada uno de los datos a tratar. 5. Acceso al siguiente elemento. 6. Tratamiento final. Terminar las acciones que queden por resolver el problema. **Ejemplo 1** | Partes | Código | | ------------------------------------------------ | ---------------------------------------------------------------------------------- | | Acceso al primer elemento | `i := 1;` | | Tratamiento inicial | `media := 0;` | | Comprobar si ya hemos llegado al último elemento | `while i <= 365 do` | | Tratar el elemento | `temperatura := readReal();`
`media := media + temperatura;`
`end while` | | Acceso al siguiente elemento | `i := i + 1` | | Tratamiento final | `writeReal(media/365.0)` | **Ejemplo 2** | Partes | Código | | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | Acceso al primer elemento | `temp := readReal();` | | Tratamiento inicial | `movieTheater.numTheaters := 0;` | | Comprobar si ya hemos llegado al último elemento | `while temp ≠ END_SEQ do` | | Tratar el elemento | `movieTheater.numTheaters := movieTheater.numTheaters + 1;`
`movieTheater.collect[movieTheater.numTheaters] := temp;`
`end while` | | Acceso al siguiente elemento | `temp := readReal();` | | Tratamiento final | - | Con lo cual, en estos dos casos se comparte el **esquema de recorrido**, ya sea para recorrer datos que leemos del canal estándar o datos de una tabla. Un patrón habitual es el siguiente: ```alg algorithm esquemaRecorrido {acceder al primer elemento} {tratamiento inicial} while not {último elemento} do {tratar elemento} {acceder al siguiente elemento} end while {tratamiento final} end algorithm ``` Tener en cuenta que: - Todos los elementos de la secuencia son del mismo tipo. - Procesamos todos los elementos de la misma manera. - Es necesario saber cómo se acaba la secuencia. ### 17.3. Esquema de búsqueda Vamos a ver un ejemplo que es lo más esclarecedor. #### 17.3.1. Ejemplo A partir de las temperaturas medias de un año que leemos por el canal estándar, averiguar el primer día que ha helado. Debemos comprobar que la temperatura es negativa. ```alg algorithm hasFrozen var t: vector[365] real; frost: boolean; i: integer; end var i:= 1; frost:= false; while i ≤ 365 and frost == false do t[i]:=readReal(); if t[i] ≤ 0 then frost:= true; end if i:=i+1: end while writeBoolean(frost); end algorithm ``` ```c #include #include int main(int argc, char** argv) { float t[365]; bool frost; int i; i = 0; frost = false; while (i < 365 && !frost) { scanf("%f", &t[i]); if (t[i] <= 0) { frost = true; } i = i + 1; } printf("%d\n", frost); /* Equivalence in C language: 0 == false, 1 == true */ return 0; } ``` Cuando encontramos el primer caso de temperatura negativa ya podemos dejar de buscar, hemos realizado una **búsqueda**. Otro caso sería si quisieramos saber cuántos días ha helado, que tendríamos que hacer un **recorrido** por todas las temperaturas. Los pasos del esquema de búsqueda son: 1. Acceder al primer elemento. 2. Tratamiento inicial. 3. Último elemento 4. Actualizar encontrado 5. Acceder al siguiente elemento. 6. Tratamiento final. | Partes | Código | | ------------------------------------------------ | ------------------------------------------------------------------------ | | Acceso al primer elemento | `i := 1;` | | Tratamiento inicial | no hace falta inicializar ninguna variable;
`encontrado := false;` | | Comprobar si ya hemos llegado al último elemento | `while i <= 365 and not encontrado do` | | Actualizar encontrado | `t[i] := readReal();`
`if t[i] ≤ 0 entonces encontrado:= true;` | | Acceso al siguiente elemento | `if not encontrado then`
`i:= i +1;`
`end if`
`end while` | | Tratamiento final | `writeBoolean(encontrado)` | Por lo tanto, este sería el **esquema de búsqueda**: ```alg algorithm esquemaBusqueda var encontrado: boolean; end var {acceder_primer_elemento} {tratamiento_inicial} encontrado:= false; while not {último elemento} and not encontrado do if {elemento tratado cumple condición} then encontrado:= true; else {acceder al siguiente elemento} end if end while {tratamiento_final} end algorithm ``` Tener en cuenta que: - Recorremos únicamente la secuencia hasta encontrar el elemento que cumple una determinada condición. - Se contempla la posibilidad de que no se encuentre el elemento buscado. - El esquema finaliza si se encuentra el elemento buscado o si se ha recorrido toda la secuencia. [Volver arriba](#pr-4)