Programación (PRG) PR´ACTICA 10. Algoritmos de búsqueda

Anuncio
Programación (PRG)
PRÁCTICA 10. Algoritmos de búsqueda
Facultad de Informática
Departamento de Sistemas Informáticos y Computación
Universidad Politécnica de Valencia
Curso 2002/2003
1.
Introducción
El objetivo de esta práctica es estudiar el comportamiento de dos algoritmos de búsqueda de elementos dentro de vectores. Los algoritmos a estudiar
son ya conocidos por el alumno, siendo uno la búsqueda secuencial y otro la
binaria.
Esta práctica trata de medir el trabajo realizado por cada uno de los
algoritmos utilizando una medida a posteriori, es decir, midiendo el trabajo que ha realizado el ordenador una vez resuelto el problema. El alumno
deberá relacionar los resultados obtenidos con los resultados esperados, derivados del estudio a priori (es decir, a partir del código fuente) del algoritmo
visto en clase.
2.
Búsqueda secuencial
Este es el algoritmo básico de búsqueda de elementos dentro de un vector.
Empieza a buscar el elemento en la primera posición y, si no lo encuentra,
continúa en la siguiente posición, y ası́ hasta encontrarlo. Los algoritmos de
búsqueda pueden terminar de dos maneras distintas: con éxito, si encuentran
el elemento, o sin éxito, si el elemento no estaba en el vector.
A continuación se muestra el algoritmo básico de búsqueda secuencial en
vectores de enteros:
int bs(int x, int V[], int i, int j) {
while (i <= j && x!=V[i]) i++;
/* i<j */
if (i<=j) return i;
/* Encontrado */
else return -1;
/* No encontrado */
}
1
Prácticas PRG. Facultad de Informática
DSIC
Curso 2002/2003
PRÁCTICA 10. Algoritmos de búsqueda
Los parámetros de la función anterior son:
x: El elemento a buscar.
V: El vector de enteros donde se realizará la búsqueda.
i: Posición inicial de la búsqueda.
j: Posición final de la búsqueda.
La función devuelve la posición del vector donde se ha encontrado el
elemento, o bien -1 si no lo ha encontrado.
El algoritmo anterior se puede mejorar de varias formas [1]:
Mediante un centinela. Se sitúa el valor que se está buscando al
final del vector, de manera que se asegura el éxito de la búsqueda.
Ası́, la comprobación de llegada al final del vector dentro del bucle se
puede eliminar. El bucle anterior quedarı́a:
while (x!=V[i]) i++;
Si el vector está ordenado. Entonces, cuando se encuentra un valor
mayor que el buscado, el algoritmo puede terminar, ya que el elemento
buscado no está en el vector. Esta modificación mejora la velocidad
del algoritmo en el caso de que el elemento no esté en el vector.
Si se sabe a priori la frecuencia de acceso a los elementos. Entonces se podrı́an colocar los elementos más frecuentemente buscados
al principio del vector. Este orden aumenta la velocidad de búsqueda
en caso de éxito.
Estas aceleraciones necesitan que el vector se pueda modificar. Cuando
el vector está implementado de tal forma que no se pueda modificar y no
se tiene ninguna información adicional sobre la disposición de sus elementos
(por ejemplo, que estén ordenados), habrá que utilizar el algoritmo básico.
3.
Búsqueda binaria
Este algoritmo necesita que el vector esté ordenado. El método de búsqueda utilizado por este algoritmo consiste en estudiar el elemento central del
vector. En función de que sea mayor o menor que el elemento buscado, se
puede restringir la búsqueda a una mitad del vector. Después, se repite el
mismo proceso con la mitad seleccionada. De esta forma, o bien se encuentra
el elemento buscado en una de las posiciones medias que se han estudiado
(salida con éxito), o bien el vector a estudiar se queda sin elementos (salida
sin éxito).
Página 2 de 6
Prácticas PRG. Facultad de Informática
DSIC
Curso 2002/2003
PRÁCTICA 10. Algoritmos de búsqueda
A continuación se muestra una implementación en C de dicho algoritmo
vista en clase:
int bb(int x, int V[], int i, int j) {
int k;
while (i < j) { k = (i+j)/2;
if (x<V[k]) j = k-1;
else if (x>V[k]) i = k+1;
else return k;
}
if (x!=V[i]) return -1;
else
return i;
}
/* i<=k<j */
/* x<V[k] */
/* x>V[k] */
/* x==V[k] */
/*i==j*/
/* caso- */
/* -base */
Los argumentos y la salida de la función de búsqueda binaria son los
mismos que los de la búsqueda secuencial.
4.
Estudio del coste temporal de un algoritmo
En la Práctica 6 ya se estudió la forma de calcular experimentalmente el
coste de los algoritmos. En este apartado se recordará cómo medir el coste
temporal de un segmento de un programa, es decir, calcular el tiempo que
ha tardado en ejecutarse dicho segmento.
Para medir tiempos, se puede utilizar la función clock del lenguaje C,
que se encuentra definida en el fichero de cabecera time.h. La cabecera de
la función es:
clock_t clock(void);
La función clock devuelve una aproximación del tiempo de procesador
consumido por el programa en ejecución. El valor que devuelve es de tipo
entero, e indica la cantidad de clocks que ha pasado desde el inicio del
programa. Para convertir este valor en segundos, hay que dividirlo por la
constante CLOCKS_PER_SEC.
Por ello, si se desea medir la cantidad de segundos que ha consumido un
conjunto de instrucciones del programa, se deberı́a utilizar una construcción
como la que sigue:
int t0,t1;
double total_secs;
[...]
t0=clock();
/* Segmento de código a medir */
t1=clock();
total_secs=((double)(t1-t0))/CLOCKS_PER_SEC;
El segmento de código a medir puede ser un conjunto de instrucciones,
Página 3 de 6
Prácticas PRG. Facultad de Informática
DSIC
Curso 2002/2003
PRÁCTICA 10. Algoritmos de búsqueda
una llamada a función o, en general, un segmento contiguo del programa
que es el que realiza el trabajo cuyo coste se desea medir.
¡Cuidado!. Asegúrate de medir únicamente lo que te interesa medir. Es un
error común incluir dentro de la medida de tiempo lı́neas de código que no
pertenecen al algoritmo que se debe medir. Por ejemplo, si se desea medir
el coste de ordenar un vector dado, el siguiente ejemplo muestra cómo no
se debe realizar la medida:
t0=clock();
printf("El tiempo total es: ");
ordena_vector(v,0,tam);
t1=clock();
printf("%12.8lf segs\n",((double)(t1-t0))/CLOCKS_PER_SEC);
Tiempos 0. Si, en algún experimento de medida de tiempos obtienes como
resultado “0” segundos, el experimento no será válido. No hay ningún
ordenador que pueda hacer un trabajo, por pequeño que sea, en tiempo
cero. El problema es la precisión del reloj, es decir, las unidades de la
función clock son demasiado grandes para medir el tiempo de ejecución
del algoritmo.
En este caso, lo que hay que hacer es ejecutar un número de veces (n) el
algoritmo cuyo coste se desea medir, hasta que la suma de los tiempos totales sea medible con cierta precisión por la función clock. Posteriormente,
para calcular el tiempo que ha tardado una ejecución del algoritmo, tan
sólo habrá que dividir el tiempo total de ejecución por n.
5.
Ejercicios propuestos
1. Estudia el caso peor de los algoritmos de búsqueda secuencial y binaria.
En ambos algoritmos, el caso peor aparece cuando el elemento buscado
no está en el vector. Para realizar el estudio temporal, se deberá medir
el tiempo que tarda cada algoritmo en buscar un elemento que no
está en el vector para tallas 2000, 4000, 6000 . . . 20000. Para ello, define
e inicializa un vector del tamaño máximo, y para cada talla n utiliza
únicamente los primeros n elementos. Puedes utilizar la plantilla que
se encuentra en el fichero:
/misc/practicas/asignaturas/prgfi/p10/midebusq.c
La salida del programa deberá ser tres columnas, parecidas a las siguientes, en las que se indica la talla del vector, el tiempo en segunPágina 4 de 6
Prácticas PRG. Facultad de Informática
DSIC
Curso 2002/2003
PRÁCTICA 10. Algoritmos de búsqueda
dos que se ha tardado en buscar un elemento en un vector mediante
búsqueda secuencial y búsqueda binaria, respectivamente.
# Talla
2000
4000
6000
8000
10000
12000
14000
16000
18000
20000
Tiempo bs
0.0000260000
0.0000500000
0.0000742000
0.0001042000
0.0001242000
0.0001482000
0.0001742000
0.0002004000
0.0002224000
0.0002482000
Tiempo bb
0.0000002900
0.0000003010
0.0000003400
0.0000003400
0.0000003610
0.0000003600
0.0000003610
0.0000003600
0.0000003800
0.0000003810
Posteriormente, utiliza el programa gnuplot para mostrar (comando
plot) las dos gráficas correspondientes a los puntos obtenidos (X=talla,
Y=tiempo), y ajusta (comando fit) los puntos anteriores mediante las
funciones que definen el coste teórico de los algoritmos.
2.
Modifica el programa anterior para que, además de contar tiempo,
cuente comparaciones. El resultado del programa tendrı́a 5 columnas
(talla, tiempo bs, comparaciones bs, tiempo bb, comparaciones bb).
¿Existe alguna relación entre los resultados obtenidos para el tiempo
de búsqueda y los obtenidos para las comparaciones efectuadas por
cada algoritmo?.
3.
Dadas las funciones obtenidas por el ajuste por mı́nimos cuadrados
sobre los puntos experimentales, predecir el comportamiento temporal
de cada algoritmo de búsqueda en el caso peor, para las tallas mostradas en la siguiente tabla:
Talla del vector
50000
100000
500000
1000000
4.
Tiempo bs
Tiempo bb
Implementa alguna de las aceleraciones del algoritmo de búsqueda secuencial mostradas en el Apartado 2 y estudia la aceleración obtenida,
comparando el algoritmo original con el modificado, siguiendo los pasos del Ejercicio 1.
Página 5 de 6
Prácticas PRG. Facultad de Informática
DSIC
Curso 2002/2003
PRÁCTICA 10. Algoritmos de búsqueda
Referencias
[1] D.E. Knuth El arte de programar ordenadores. Vol. 3. Clasificación y
búsqueda. Ed. Reverté. 1987.
Página 6 de 6
Descargar