MÉTODOS DE BÚSQUEDA Pedro Guea Salgado Luís Olascoaga Universidad de Córdoba Facultad de Ciencias Básicas e Ingenierías Departamento de Ingeniería de Sistemas y Telecomunicaciones
MÉTODOS DE BÚSQUEDA Los métodos de búsqueda nos permiten recuperar información de un vector o un archivo, que contenga una lista de datos. Por ejemplo se puede obtener el nombre y el número telefónico de nuestra aga de contactos o la nota obtenida por un alumno en la lista de un curso. Cuando se realizan búsquedas sobre vectores, se desea es encontrar la posición que ocupa el elemento buscado dentro de la lista de elementos que contiene el vector. Para la búsqueda de información en archivos es necesario realizar la búsqueda a partir de un campo clave dentro del archivo. Existen diferentes métodos de búsqueda y se puede determinar con cual método trabajar depio de la cantidad de elementos que existan en el vector o la organización de dichos elementos. A continuación para determinar si un elemento pertenece a un conjunto de elementos e indicar su posición dentro de un vector, utilizaremos los métodos de búsqueda secuencial (lineal) y búsqueda binaria. Búsqueda Secuencial o Lineal: En este método se recorre el vector desde el primer elemento hasta el ultimo, comparando cada elemento del vector con el valor buscado, hasta que se encuentre el elemento o se llegue al final del vector. Este método es recomado para realizar búsquedas con pocos datos. Implementación del método que busca lineal o secuencial, y devuelve la posición del dato a buscar que se pasa como parámetro: function TBusquedas.busquedaLineal(dato: string): integer; i:integer; //iable para controlar el ciclo while. pos:integer; //iable que devuelve la posición en la que se encuentra el elemento en el vector. //Asigno el valor de -1 a la iable pos para devolver este valor en el supuesto caso de que no se encuentre //el valor buscado dentro del vector. pos:=-1; i:=1; //Mientras que no se llegue al final del vector y no se haya encontrado el dato buscado en el vector. while (i <= num) and (pos = -1) do //Si el contenido del vector en la posición i-esima es igual al dato que se esta buscando entonces el dato si //esta en el vector y devuelvo la posición en donde se encuentra el dato dentro del vector. Sino el dato no se //encuentra en esa posición, entonces incremento la posición (i) para realizar una nueva comparación. if getvector(i) = dato then pos:=i; i:=i+1;
//Al final retorno la posición en donde se encuentra el elemento buscado. Result:=pos; Búsqueda Binaria: Este método es una técnica eficaz para realizar búsquedas en vectores o archivos que contengan un mayor número de datos. Este método divide el vector en mitades de manera sucesiva hasta que encuentra el dato buscado, es decir, el método divide el vector y se examina el elemento central del vector. Si es el elemento que se busca, entonces la búsqueda finaliza, pero sino se determina si el dato buscado esta en la primera o la segunda mitad del vector y se repite el proceso en la nueva mitad, buscando su elemento central. Para realizar la búsqueda binaria el vector debe estar ordenado y se comienza comparando con el elemento central. Implementación del método que busca de manera binaria, y devuelve la posición del dato a buscar que se pasa como parámetro: function TBusquedas.bsuquedaBinaria(dato: string): integer; //Variables para controlar las diferentes posiciones el vector. pos, izq, der, centro:integer; //Es necesario primero ordenar el vector con algún método de ordenamiento. ordenarintercambio; izq:=1; der:=num; //Asigno el valor de -1 a la iable pos para devolver este valor en el supuesto caso de que no se encuentre //el valor buscado dentro del vector. pos:=-1; //Mientras que no se llegue al final del vector y no se haya encontrado el dato buscado en el vector. while (izq <= der) and (pos = -1) do //Busco cual es la posición del dato que se encuentra en el centro del vector, utilizo div para que la posición //siempre de un valor entero. centro:=(izq+der) div 2; //Si el dato es igual a lo que tiene el vector en la posición del centro, entonces ya encontró el elemento //buscado y se devuelve la posición en donde se encontró, pero sino entonces se determina si el elemento //esta a la izquierda o a la derecha del vector. Y se procede a buscar el dato hacia el inicio del vector //(izquierda) o hacia el final del vector (derecha), esto si el dato buscado es mayor o menor al elemento que //se encuentra en el centro del vector. if dato = getvector(centro) then pos:=centro; if dato < getvector(centro) then //Reducimos el extremo derecho, moviolo hacia el inicio del vector (izquierda). der:=centro-1; //El elemento esta a la derecha del centro y hacemos el recorrido hacia el final del vector (derecha). izq:=centro+1;
//Al final retorno la posición en donde se encuentra el elemento buscado. Result:=pos; A continuación implementaremos un ejercicio que permite almacenar una cantidad especifica de teléfonos celulares en un vector y posteriormente implementamos los métodos de búsqueda descritos anteriormente, para determinar si un número celular se encuentra almacenado dentro del vector. Creamos un nuevo proyecto para implementar el ejercicio y automáticamente se crea una unidad con la clase TForm1. Procedemos a guardar esta unidad con el nombre UVentanaBusquedas, para implementar todo el cógido que trá el formulario. A continuación se crea la unidad en donde se implementara el código de la clase lógica y se guarda con el nombre UMetodosBusqueda. En esta clase se declara el vector y sus respectivos métodos selectores, modificadores, así como los métodos de búsqueda que solucionan el problema planteado. Para el diseño del formulario (clase TForm1), en donde se capturan los datos y se muestra la información, se utilizaran los siguientes componentes con sus respectivos nombres: Tres TEdit (campos de texto), uno para mostrar las diferentes posiciones de cada indice en el vector, uno para capturar los teléfonos celulares y otro para realizar las búsquedas. Los nombres que se utilizaran para los TEdit son: posi, val y bus respectivamente. Un TUpDown que llamaremos Up para ir incrementando las posiciones del campo de texto posi de manera automática. Tenemos que tener en cuenta la propiedad Associate del TUpDown (Up) para asociarlo con el TEdit (posi) e iniciar la propiedad Max en 1. Cuatro TButton (botones), para ir guardando los elementos, mostrar los elementos del vector, limpiar y salir de la aplicación. Los nombres que se utilizaran para los TButton son: bguardar, bmostrar, blimpiar y bsalir respectivamente. Un TListBox de nombre lisvec para visualizar el contenido del vector, a medida que se almacenen elementos en el vector. Un TComboBox de nombre op para seleccionar con que método (secuencial o binaria) queremos realizar la búsqueda en el vector. El TComboBox (op) en la propiedad Items trá las opciones: Secuencial y Binaria. También se utilizaran ios TLabel para colocar los diferentes comentarios que aparecen en el formulario.
La apariencia del formulario sera lago parecida a la siguiente ventana: Implementación de la clase lógica TBusquedas en la unidad UMetodosBusqueda: unit UMetodosBusqueda; {$mode objfpc}{$h+} interface uses Classes, SysUtils; const num=20; type { TBusquedas } TBusquedas=class private vector:array[1..num] of string; public constructor create; procedure setvector(p:integer; ve:string); function getvector(p:integer):string; //Declaración del método que retorna la posición del dato buscado, utilizando el método de búsqueda lineal //o secuencial. El método recibe como parámetro el dato que se desea buscar dentro del arreglo. function busquedalineal(dato:string):integer; //Declaración del método de ordenamiento por intercambio, este método se utilizara en la implementación //del método de búsqueda binaria ya que para la búsqueda binaria se requiere que los elementos del vector //estén ordenados.
procedure ordenarintercambio; //Declaración del método que retorna la posición del dato buscado, utilizando el método de búsqueda binaria //el método recibe como parámetro el dato que se desea buscar dentro del arreglo. function bsuquedabinaria(dato:string):integer; implementation { TBusquedas } constructor TBusquedas.create; i:integer; for i:=1 to num do vector[i]:='0'; procedure TBusquedas.setVector(p: integer; ve: string); vector[p]:=ve; function TBusquedas.getVector(p: integer): string; Result:=vector[p]; //Implementación del método que busca lineal o secuencialmente los datos en el vector. Ya se documento el //código anteriormente. function TBusquedas.busquedaLineal(dato: string): integer; i:integer; pos:integer; pos:=-1; i:=1; while (i <= num) and (pos = -1) do if getvector(i) = dato then pos:=i; i:=i+1; Result:=pos; //Implementación del método de ordenamiento por intercambio. Este método es necesario para ordenar el //vector en el método de búsqueda binaria. procedure TBusquedas.ordenarIntercambio; i,j:integer; temp:string; for i:=1 to num do for j:=i+1 to num do if getvector(i) > getvector(j) then
temp:=getvector(i); setvector(i, getvector(j)); setvector(j, temp); //Implementación del método de búsqueda binaria. function TBusquedas.bsuquedaBinaria(dato: string): integer; pos, izq, der, centro:integer; ordenarintercambio; izq:=1; der:=num; pos:=-1; while (izq <= der) and (pos = -1) do centro:=(izq+der) div 2; if dato = getvector(centro) then pos:=centro; if dato < getvector(centro) then der:=centro-1; izq:=centro+1; Result:=pos;. Implementación de la clase lógica TForm1 en la unidad UVentanaBusquedas: unit UVentanaBusquedas; {$mode objfpc}{$h+} interface uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, UMetodosBusqueda,StdCtrls, ComCtrls; type { TForm1 } TForm1 = class(tform) bguardar: TButton; bus: TEdit; bmostrar: TButton; blimpiar: TButton;
bsalir: TButton; op: TComboBox; Label4: TLabel; Label5: TLabel; Label6: TLabel; lisvec: TListBox; val: TEdit; Label3: TLabel; posi: TEdit; Label1: TLabel; Label2: TLabel; Up: TUpDown; procedure FormClose(Ser: TObject; CloseAction: TCloseAction); procedure FormCreate(Ser: TObject); procedure FormShow(Ser: TObject); procedure bguardarclick(ser: TObject); procedure blimpiarclick(ser: TObject); procedure bmostrarclick(ser: TObject); procedure bsalirclick(ser: TObject); procedure opchange(ser: TObject); private //Declaramos la instancia global (para que la usen todos los botones) y privada (atributo de la ventana). vec:tbusquedas; //Método para mostrar los elementos del vector en el TListBox (lisvec). procedure mostrar; public { public declarations } Form1: TForm1; implementation { TForm1 } //Implementación del evento OnShow para colocar el cursor en el TEdit de nombre val. procedure TForm1.FormShow(Ser: TObject); val.setfocus; //implementación del código para el evento del botón guardar. procedure TForm1.bGuardarClick(Ser: TObject); vec.setvector(up.position, val.text); if Up.Position < num then Up.Position:=Up.Position+1; mostrar; val.clear; val.setfocus; //implementación del evento para el botón limpiar. procedure TForm1.bLimpiarClick(Ser: TObject); i:integer; lisvec.clear; for i:=1 to num do vec.setvector(i, '');
Up.Position:=1; val.clear; bus.clear; val.setfocus; //implementación del evento para el botón mostrar. procedure TForm1.bMostrarClick(Ser: TObject); mostrar; //implementación del evento para el botón salir. procedure TForm1.bSalirClick(Ser: TObject); Close; //Método que permite seleccionar el método de búsqueda deseado (secuencial o binaria). procedure TForm1.opChange(Ser: TObject); dato:string; pos:integer; if op.text = 'Secuencial' then dato:=bus.text; pos:=vec.busquedalineal(dato); if pos <> -1 then ShowMessage('El No. celular '+dato+' se encuentra en la posiscion '+IntToStr(pos)); ShowMessage('El No. celular '+dato+' No se encuentra en el vector'); dato:=bus.text; pos:=vec.bsuquedabinaria(dato); if pos <> -1 then ShowMessage('El No. celular '+dato+' se encuentra en la posiscion '+IntToStr(pos)); ShowMessage('El No. celular '+dato+' No se encuentra en el vector'); //implementación del método para el evento constructor del formulario. Para implementar este código solo //basta con seleccionar el formulario y escoger en el inspector de objetos, el evento OnCreate. procedure TForm1.FormCreate(Ser: TObject); vec:=tbusquedas.create; Up.Max:=num; //implementación del método que libera la instancia, para implementar este código solo basta con //seleccionar el formulario y escoger en el inspector de objetos, el evento OnClose.
procedure TForm1.FormClose(Ser: TObject; CloseAction: TCloseAction); vec.free; //implementación del método que muestra los elementos del vector en TListBox (lisvec). procedure TForm1.mostrar; i:integer; lisvec.clear; for i:=1 to num do lisvec.items.add('posicion '+IntToStr(i)+'= '+ vec.getvector(i)); initialization {$I uventanabusquedas.lrs}.