algoritmos y estructuras de datos

Upload: mmarquez55

Post on 14-Oct-2015

30 views

Category:

Documents


0 download

DESCRIPTION

Capítulo 6, Algoritmos de búsqueda/

TRANSCRIPT

  • 6ALGORITMOS

    DE ORDENACIN Y BSQUEDA

    OBJETIVOSDespus del estudio de este captulo ustedpodr: Conocer los algoritmos basados en el inter-

    cambio de elementos. Conocer el algoritmo de ordenacin por in-

    sercin. Conocer el algoritmo de seleccin. Distinguir entre los algoritmos de ordena-

    cin basados en el intercambio y en la in-sercin.

    Deducir la eficiencia de los mtodos bsi-cos de ordenacin.

    Conocer los mtodos ms eficientes de or-denacin.

    Aplicar mtodos mas eficientes de ordena-cin de arrays (arreglos).

    Diferenciar entre bsqueda secuencial ybsqueda binaria.

    CONTENIDO6.1. Ordenacin.6.2. Algoritmos de ordenacin bsicos.6.3. Ordenacin por intercambio.6.4. Ordenacin por seleccin.6.5. Ordenacin por insercin.

    6.6. Ordenacin por burbuja.6.7. Ordenacin Shell.6.8. Ordenacin rpida (quicksort).6.9. Ordenacin Binsort y Radixsort.

    6.10. Bsqueda en listas: bsqueda secuen-cial y binaria.

    RESUMEN

    EJERCICIOS

    PROBLEMAS

    CONCEPTOS CLAVE Ordenacin numrica. Ordenacin alfabtica. Complejidad cuadrtica. Ordenacin por burbuja. Ordenacin rpida. Residuos. Ordenacin por intercambio. Ordenacin por insercin. Bsqueda en listas: bsqueda secuencial y

    bsqueda binaria. Complejidad logartmica. Ordenacin por seleccin.

    INTRODUCCINMuchas actividades humanas requieren que en ellas las diferentes colecciones de elementos utili-zados se coloquen en un orden especfico. Las oficinas de correo y las empresas de mensajeraordenan el correo y los paquetes por cdigos postales con el objeto de conseguir una entregaeficiente; los anuarios o listines telefnicos ordenan sus clientes por orden alfabtico de apelli-dos con el fin ltimo de encontrar fcilmente el nmero de telfono deseado; los estudiantes de

    165

  • una clase en la universidad se ordenan por sus apellidos o por los nmeros de expediente, etc. Poresta circunstancia una de las tareas que realizan ms frecuentemente las computadoras en elprocesamiento de datos es la ordenacin.

    El estudio de diferentes mtodos de ordenacin es una tarea intrnsecamente interesantedesde un punto de vista terico y, naturalmente, prctico. El captulo estudia los algoritmos ytcnicas de ordenacin ms usuales y su implementacin en C. De igual modo se estudiar el anli-sis de los algoritmos utilizados en diferentes mtodos de ordenacin con el objetivo de conseguirla mxima eficiencia en su uso real. En el captulo se analizarn los mtodos bsicos y avanzadosms empleados en programas profesionales.

    6.1. ORDENACINLa ordenacin o clasificacin de datos (sort, en ingls) es una operacin consistente en disponerun conjunto estructura de datos en algn determinado orden con respecto a uno de los camposde elementos del conjunto. Por ejemplo, cada elemento del conjunto de datos de una gua telefnicatiene un campo nombre, un campo direccin y un campo nmero de telfono; la gua telefnica estdispuesta en orden alfabtico de nombres; los elementos numricos se pueden ordenar en ordencreciente o decreciente de acuerdo al valor numrico del elemento. En terminologa de ordenacin,el elemento por el cual est ordenado un conjunto de datos (o se est buscando) se denomina clave.

    Una coleccin de datos (estructura) puede ser almacenada en un archivo, un array (vector otabla), un array de registros, una lista enlazada o un rbol. Cuando los datos estn almacenados enun array, una lista enlazada o un rbol, se denomina ordenacin interna. Si los datos estn almace-nados en un archivo, el proceso de ordenacin se llama ordenacin externa.

    Una lista se dice que est ordenada por la clave k si la lista est en orden ascendente o descen-dente con respecto a esta clave. La lista se dice que est en orden ascendente si:

    i < j implica que k[i] j implica que k[i]

  • As, en el caso de ordenar los elementos de un vector, el nmero de comparaciones ser funcin delnmero de elementos (n) del vector (array). Por consiguiente, se puede expresar el nmero decomparaciones en trminos de n (por ejemplo, n+ 4, o bien n2 en lugar de nmeros enteros (porejemplo, 325).

    En todos los mtodos de este captulo, normalmente para comodidad del lector se utiliza elorden ascendente sobre vectores o listas (arrays unidimensionales).

    Los mtodos de ordenacin se suelen dividir en dos grandes grupos:

    directos burbuja, seleccin, insercin indirectos (avanzados) Shell, ordenacin rpida, ordenacin por mezcla, Radixsort

    En el caso de listas pequeas, los mtodos directos se muestran eficientes, sobre todo porque losalgoritmos son sencillos; su uso es muy frecuente. Sin embargo, en listas grandes estos mtodos semuestran ineficaces y es preciso recurrir a los mtodos avanzados.

    6.2. ALGORITMOS DE ORDENACIN BSICOSExisten diferentes algoritmos de ordenacin elementales o bsicos cuyos detalles de implemen-tacin se pueden encontrar en diferentes libros de algoritmos. La enciclopedia de referencia es[KNUTH 1973]1 y sobre todo la 2.a edicin publicada en el ao 1998 [KNUTH 1998]2. Los algorit-mos presentan diferencias entre ellos que los convierten en ms o menos eficientes y prcticossegn sea la rapidez y eficiencia demostrada por cada uno de ellos. Los algoritmos bsicos deordenacin ms simples y clsicos son:

    Ordenacin por seleccin. Ordenacin por insercin. Ordenacin por burbuja.

    Los mtodos ms recomendados son: seleccin e insercin, aunque se estudiar el mtodo deburbuja, por aquello de ser el ms sencillo aunque a la par tambin es el ms ineficiente; por estacausa no recomendamos su uso, pero s conocer su tcnica.

    Los datos se pueden almacenar en memoria central o en archivos de datos externos guardadosen unidades de almacenamiento magntico (discos, cintas, disquetes, CD-ROM, DVD, discos flashUSB, etc.) Cuando los datos se guardan en listas y en pequeas cantidades, se suelen almacenar demodo temporal en arrays y registros; estos datos se almacenan exclusivamente para tratamientosinternos que se utilizan en gestin masiva de datos y se guardan en arrays de una o varias dimensio-nes. Los datos, sin embargo, se almacenan de modo permanente en archivos y bases de datos que seguardan en discos y cintas magnticas.

    A tener en cuentaExisten dos tcnicas de ordenacin fundamentales en gestin de datos: ordenacin de listasy ordenacin de archivos. Los mtodos de ordenacin se conocen como internos o externossegn que los elementos a ordenar estn en la memoria principal o en la memoria externa.

    1 [KNUTH 1973] Donald E. Knuth. The Art of Computer Programming. Volume 3: Sorting and Searching. Addison-Wesley,1973.

    2 [KNUTH 1998] Donald E. Knuth. The Art of Computer Programming. Volume 3: Sorting and Searching. Second Edition.Addison-Wesley, 1998.

    Algoritmos de ordenacin y bsqueda 167

  • As pues, existen dos tcnicas de ordenacin fundamentales en gestin de datos: ordenacin delistas y ordenacin de archivos. Los mtodos de ordenacin se conocen como internos o externossegn que los elementos a ordenar estn en la memoria principal o en la memoria externa.

    Las tcnicas que se analizarn a continuacin considerarn, esencialmente, la ordenacin deelementos de una lista (array) en orden ascendente. En cada caso se desarrollar la eficienciacomputacional del algoritmo.

    Con el objeto de facilitar el aprendizaje del lector y aunque no sea un mtodo utilizado por supoca eficiencia se describir en primer lugar el mtodo de ordenacin por intercambio con unprograma completo que manipula a la correspondiente funcin ordIntercambio(), por la senci-llez de su tcnica y con el objetivo de que el lector no introducido en algoritmos de ordenacinpueda comprender su funcionamiento y luego asimilar ms eficazmente los algoritmos bsicos yacitados y los avanzados que se estudiarn ms adelante.

    6.3. ORDENACIN POR INTERCAMBIOEl algoritmo de ordenacin tal vez ms sencillo sea el denominado de intercambio que ordena loselementos de una lista en orden ascendente. Este algoritmo se basa en la lectura sucesiva de la listaa ordenar, comparando el elemento inferior de la lista con los restantes y efectuando intercambio deposiciones cuando el orden resultante de la comparacin no sea el correcto.

    El algoritmo se ilustra con la lista original 8, 4,6,2 que ha de convertirse en la lista ordenada2,4, 6,8. El algoritmo realiza n 1 pasadas (3 en el ejemplo), siendo n el nmero de elementos, yejecuta las siguientes operaciones.

    a[0] a[1] a[2] a[3]

    Pasada 0 8 4 6 2 se realiza intercambio 4 8 6 2mbbb

    4 8 6 2 no se realiza intercambio 4 8 6 2mbbbbbb

    4 8 6 2 se realiza intercambio 2 8 6 4mbbbbbbbbb

    Lista inicial Lista resultante

    El elemento de ndice 0 (a[0]) se compara con cada elemento posterior de la lista de ndi-ces 1, 2 y 3. En cada comparacin se comprueba si el elemento siguiente es ms pequeo que elelemento de ndice 0, en ese caso se intercambian. Despus de terminar todas las comparaciones,el elemento ms pequeo se localiza en el ndice 0.

    Pasada 1

    El elemento ms pequeo ya est localizado en el ndice 0, y se considera la sublista restan-te 8, 6, 4. El algoritmo contina comparando el elemento de ndice 1 con los elementos posterio-res de ndices 2 y 3. Por cada comparacin, si el elemento mayor est en el ndice 1 se intercambian

    168 Algoritmos y estructuras de datos

  • los elementos. Despus de hacer todas las comparaciones, el segundo elemento ms pequeo de lalista se almacena en el ndice 1.

    2 8 6 4 intercambio 2 6 8 4mbbb

    bbbbn

    2 6 8 4 intercambio 2 4 8 6mbbbbbb

    bbbbn

    Lista inicial Lista resultante

    Pasada 2

    La sublista a considerar ahora es 8, 6 ya que 2, 4 est ordenada. Una comparacin nica seproduce entre los dos elementos de la sublista

    2 4 8 6 intercambio 2 4 6 8mbbb

    bbbbn

    Lista inicial Lista resultante

    El mtodo ordIntercambio utiliza dos bucles anidados. Suponiendo que la lista es de tama-o n, el rango del bucle externo ir desde el ndice 0 hasta n 2. Por cada ndice i, se comparan loselementos posteriores de ndices j = i + 1, i + 2, ..., n 1. El intercambio (swap) de los elementosa[i],a[j] se realiza en un bloque que utiliza el algoritmo siguiente:

    aux = a[i];a[i] = a[j];a[j]= aux ;

    Ejercicio 6.1El programa siguiente ordena una lista de n elementos de tipo entero introducida en un array yposteriormente la imprime (o visualiza) en pantalla.

    #include #define N 100

    void ordIntercambio (int a[], int n);void entradaLista (int a[], int n);void imprimirLista (int a[], int n);

    int main(){

    int n;int v[N];

    Algoritmos de ordenacin y bsqueda 169

  • do {printf("\nIntroduzca el nmero de elementos: ");scanf("%d", &n);

    } while ((n < 1) && (n > N));

    entradaLista(v, n);/* muestra lista original */

    printf("\nLista original de %d elementos", n);imprimirLista(v, n);

    /* ordenacin ascendente de la lista */ordIntercambio(v, n);printf("\nLista ordenada de %d elementos", n);imprimirLista(v, n);return 0;

    }

    void ordIntercambio (int a[], int n){

    int i, j;

    /* se realizan n1 pasadas *//* a[o], ... , a[n-2] */

    for (i = 0 ; i

  • {printf("a[%d] = ",);scanf("%d", a+i);

    }}

    6.4. ORDENACIN POR SELECCINConsidrese el algoritmo para ordenar un array A de enteros en orden ascendente, es decir, delnmero ms pequeo al mayor. Es decir, si el array A tiene n elementos, se trata de ordenar losvalores del array de modo que el dato contenido en A[0] sea el valor ms pequeo, el valor almace-nado en A[1] el siguiente ms pequeo, y as hasta A[n-1], que ha de contener el elemento demayor valor. El algoritmo se apoya en sucesivas pasadas que intercambian el elemento ms peque-o sucesivamente con el primer elemento de la lista, A[0] en la primera pasada. En sntesis, sebusca el elemento ms pequeo de la lista y se intercambia con A[0], primer elemento de la lista.

    A[0] A[1] A[2].... A[n-1]

    Despus de terminar esta primera pasada, el frente de la lista est ordenado y el resto de la listaA[1], A[2]...A[n-1] permanece desordenado. La siguiente pasada busca en esta lista desorde-nada y selecciona el elemento ms pequeo, que se almacena entonces en la posicin A[1]. Deeste modo los elementos A[0] y A[1] estn ordenados y la sublista A[2], A[3]...A[n-1] de-sordenada; entonces, se selecciona el elemento ms pequeo y se intercambia con A[2]. El procesocontina n 1 pasadas y en ese momento la lista desordenada se reduce a un elemento (el mayor dela lista) y el array completo ha quedado ordenado.

    Un ejemplo prctico ayudar a la comprensin del algoritmo. Consideremos un array A con 5valores enteros 51, 21, 39, 80, 36:

    A[0] A[1] A[2] A[3] A[4]

    51 21 39 80 36 Pasada 0. Seleccionar 21Intercambiar 21 y A[0]

    pasada 0

    21 51 39 80 36 Pasada 1. Seleccionar 36Intercambiar 36 y A[1]

    pasada 1

    21 36 39 80 51 Pasada 2. Seleccionar 39Intercambiar 39 y A[2]

    pasada 2

    21 36 39 80 51 Pasada 3. Seleccionar 51Intercambiar 51 y A[3]

    pasada 3

    21 36 39 51 80 Lista ordenada

    Algoritmos de ordenacin y bsqueda 171

  • 6.4.1. Algoritmo de seleccin

    Los pasos del algoritmo son:

    1. Seleccionar el elemento ms pequeo de la lista A; intercambiarlo con el primer elementoA[0]. Ahora la entrada ms pequea est en la primera posicin del vector.

    2. Considerar las posiciones de la lista A[1], A[2], A[3]..., seleccionar el elemento mspequeo e intercambiarlo con A[1]. Ahora las dos primeras entradas de A estn en orden.

    3. Continuar este proceso encontrando o seleccionando el elemento ms pequeo de los res-tantes elementos de la lista, intercambindolos adecuadamente.

    6.4.2. Codificacin en C del algoritmo de seleccin

    La funcin ordSeleccion() ordena una lista o vector de nmeros reales de n elementos. En lapasada i, el proceso de seleccin explora la sublista A[i] a A[n-1] y fija el ndice del elementoms pequeo. Despus de terminar la exploracin, los elementos A[i] y A[indiceMenor] in-tercambian las posiciones.

    /*ordenar un array de n elementos de tipo doubleutilizando el algoritmo de ordenacin por seleccin

    */

    void ordSeleccion (double a[], int n){

    int indiceMenor, i, j;/* ordenar a[0]..a[n-2] y a[n-1] en cada pasada */

    for (i = 0; i < n-1; i++){

    /* comienzo de la exploracin en ndice i */indiceMenor = i;

    /* j explora la sublista a[i+1]..a[n-1] */for (j = i+1; j < n; j++)

    if (a[j] < a[indiceMenor])indiceMenor = j;

    /* sita el elemento ms pequeo en a[i] */if (i != indiceMenor){

    double aux = a[i];a[i] = a[indiceMenor];a[indiceMenor] = aux ;

    }}

    }

    El anlisis del algoritmo de seleccin es sencillo y claro, ya que requiere un nmero fijo decomparaciones que slo dependen del tamao de la lista o vector (array) y no de la distribucininicial de los datos. En el Apartado 2.6.1 se realiz un estudio de la complejidad de este algoritmo.

    172 Algoritmos y estructuras de datos

  • 6.5. ORDENACIN POR INSERCINEl mtodo de ordenacin por insercin es similar al proceso tpico de ordenar tarjetas de nombres(cartas de una baraja) por orden alfabtico, que consiste en insertar un nombre en su posicincorrecta dentro de una lista o archivo que ya est ordenado. As el proceso en el caso de la lista deenteros A = 50, 20, 40, 80, 30.

    Procesar 20 50 Comienzo con 50

    Procesar 20 20 50 Se inserta 20 en la posicin 0 50 se mueve a posicin 1

    Procesar 40 20 40 50 Se inserta 40 en la posicin 1 Se mueve 50 a posicin 2

    Procesar 80 20 40 50 80 El elemento 80 est bien ordenado

    Procesar 30 20 30 40 50 80 Se inserta 30 en posicin 1 Se desplaza a la derecha la sublista derecha

    Figura 6.1. Mtodo de ordenacin por insercin.

    6.5.1. Algoritmo de ordenacin por insercin

    El algoritmo correspondiente a la ordenacin por insercin contempla los siguientes pasos:1. El primer elemento A[0] se considera ordenado; es decir, la lista inicial consta de un

    elemento.2. Se inserta A[1] en la posicin correcta, delante o detrs de A[0], dependiendo de que sea

    menor o mayor.3. Por cada bucle o iteracin i (desde i=1 hasta n-1) se explora la sublista A[i-1] ..

    A[0] buscando la posicin correcta de insercin; a la vez se mueve hacia abajo (a la dere-cha en la sublista) una posicin todos los elementos mayores que el elemento a insertarA[i], para dejar vaca esa posicin.

    4. Insertar el elemento a la posicin correcta.

    6.5.2. Codificacin en C del algoritmo de ordenacin por insercin

    La funcin ordInsercion() tiene dos argumentos, el array a[] que se va a ordenar creciente-mente, y el nmero de elementos n. En la codificacin se supone que los elementos son de tipoentero.

    void ordInsercion (int [] a, int n){

    int i, j;int aux;

    for (i = 1; i < n; i++){

    /* ndice j explora la sublista a[i-1]..a[0] buscando laposicin correcta del elemento destino, lo asigna a a[j] */

    Algoritmos de ordenacin y bsqueda 173

  • j = i;aux = a[i];/* se localiza el punto de insercin explorando hacia abajo */while (j > 0 && aux < a[j-1]){

    /* desplazar elementos hacia arriba para hacer espacio */a[j] = a[j-1];j--;

    }a[j] = aux;

    }}

    El anlisis del algoritmo de insercin se realiz como ejemplo en el Apartado 2.6.2, se determi-n que la complejidad del algoritmo es 0(n2), complejidad cuadrtica.

    6.6. ORDENACIN POR BURBUJAEl mtodo de ordenacin por burbuja es el ms conocido y popular entre estudiantes y aprendicesde programacin, por su facilidad de comprensin y programacin; por el contrario, es el menoseficiente y por ello, normalmente, se aprende su tcnica pero no suele utilizarse.

    La tcnica utilizada se denomina ordenacin por burbuja u ordenacin por hundimiento debi-do a que los valores ms pequeos burbujean gradualmente (suben) hacia la cima o parte superiordel array de modo similar a como suben las burbujas en el agua, mientras que los valores mayoresse hunden en la parte inferior del array. La tcnica consiste en hacer varias pasadas a travs delarray. En cada pasada, se comparan parejas sucesivas de elementos. Si una pareja est en ordencreciente (o los valores son idnticos), se dejan los valores como estn. Si una pareja est en or-den decreciente, sus valores se intercambian en el array.

    6.6.1. Algoritmo de la burbujaEn el caso de un array (lista) con n elementos, la ordenacin por burbuja requiere hasta n 1 pa-sadas. Por cada pasada se comparan elementos adyacentes y se intercambian sus valores cuando elprimer elemento es mayor que el segundo elemento. Al final de cada pasada, el elemento mayor haburbujeado hasta la cima de la sublista actual. Por ejemplo, despus que la pasada 0 est comple-ta, la cola de la lista A[n 1] est ordenada y el frente de la lista permanece desordenado. Las etapasdel algoritmo son:

    En la pasada 0 se comparan elementos adyacentes:

    (A[0],A[1]),(A[1],A[2]),(A[2],A[3]),...(A[n-2],A[n-1])

    Se realizan n 1 comparaciones, por cada pareja (A[i],A[i+1]) se intercambian losvalores si A[i+1] < A[i]. Al final de la pasada, el elemento mayor de la lista est situado enA[n-1].

    En la pasada 1 se realizan las mismas comparaciones e intercambios, terminando con elelemento segundo mayor valor en A[n-2].

    El proceso termina con la pasada n 1, en la que el elemento ms pequeo se almacena enA[0].

    174 Algoritmos y estructuras de datos

  • El algoritmo tiene una mejora inmediata, el proceso de ordenacin puede terminar en la pasadan 1, o bien antes, si en una pasada no se produce intercambio alguno entre elementos del vector esporque ya est ordenado, entonces no es necesario ms pasadas.

    El ejemplo siguiente ilustra el funcionamiento del algoritmo de la burbuja con un array de 5elementos (A = 50, 20, 40, 80, 30), donde se introduce una variable interruptor para detectarsi se ha producido intercambio en la pasada.

    Pasada 0 50 20 40 80 30 Intercambio 50 y 20mbbb

    Pasada 0 20 50 40 80 30 Intercambio 50 y 40mbbb

    Pasada 0 20 40 50 80 30 50 y 80 ordenadosmbbb

    Pasada 0 20 40 50 80 30 Intercambio 80 y 30mbbb

    Pasada 0 20 40 50 30 80 Elemento mayor es 80 interruptor = TRUE

    En la pasada 1:

    Pasada 0 20 40 50 30 80 20 y 40 ordenadosmbbb

    Pasada 0 20 40 50 30 80 40 y 50 ordenadosmbbb

    Pasada 0 20 40 50 30 80 Se intercambian 50 y 30mbbb

    Pasada 0 20 40 30 50 80 50 y 80 elementos mayores y ordenados interruptor = TRUE

    En la pasada 2, slo se hacen dos comparaciones:

    Pasada 0 20 40 30 50 80 20 y 40 ordenadosmbbb

    Pasada 0 20 30 40 50 80 Se intercambian 40 y 30 interruptor = TRUE

    mbbb

    Algoritmos de ordenacin y bsqueda 175

  • En la pasada 3, se hace una nica comparacin de 20 y 30, y no se produce intercambio:

    Pasada 0 20 30 40 50 80 20 y 30 ordenadosmbbb

    Pasada 0 20 30 40 50 80 Lista ordenada interruptor = FALSE

    En consecuencia, el algoritmo de ordenacin de burbuja mejorado contempla dos bucles anida-dos: el bucle externo controla la cantidad de pasadas (al principio de la primera pasada todava no seha producido ningn intercambio, por tanto la variable interruptor se pone a valor falso (0); elbucle interno controla cada pasada individualmente y cuando se produce un intercambio, cambia elvalor de interruptor a verdadero (1).

    El algoritmo terminar, bien cuando se termine la ltima pasada (n 1) o bien cuando el valordel interruptor sea falso (0), es decir, no se haya hecho ningn intercambio. La condicin pararealizar una nueva pasada se define en la expresin lgica

    (pasada < n-1) && interruptor

    6.6.2. Codificacin en C del algoritmo de la burbujaLa funcin ordBurbuja() implementa el algoritmo de ordenacin de la burbuja; tiene dos argu-mentos, el array que se va a ordenar crecientemente, y el nmero de elementos n. En la codificacinse supone que los elementos son de tipo entero largo.

    void ordBurbuja (long a[], int n){

    int interruptor = 1;int pasada, j;

    for (pasada = 0; pasada < n-1 && interruptor; pasada++){

    /* bucle externo controla la cantidad de pasadas */interruptor = 0;for (j = 0; j < n-pasada-1; j++)

    if (a[j] > a[j+1]){

    /* elementos desordenados, es necesario intercambio */long aux;interruptor = 1;aux = a[j];a[j] = a[j+1];a[j+1] = aux;

    }}

    }

    Una modificacin al algoritmo anterior puede ser utilizar, en lugar de una variable banderainterruptor, una variable indiceIntercambio que se inicie a 0 (cero) al principio de cada

    176 Algoritmos y estructuras de datos

  • pasada y se establezca al ndice del ltimo intercambio, de modo que cuando al terminar la pasadael valor de indiceIntercambio siga siendo 0 implicar que no se ha producido ningn intercam-bio (o bien, que el intercambio ha sido con el primer elemento), y, por consiguiente, la lista estarordenada. En caso de no ser 0, el valor de indiceIntercambio representa el ndice del vector apartir del cual los elementos estn ordenados. La codificacin en C de esta alternativa es:

    /*Ordenacin por burbuja : array de n elementosSe realizan una serie de pasadas mientras indiceIntercambio > 0

    */

    void ordBurbuja2 (long a[], int n){

    int i, j;int indiceIntercambio;

    /* i es el ndice del ltimo elemento de la sublista */i = n-1;

    /* el proceso contina hasta que no haya intercambios */while (i > 0){

    indiceIntercambio = 0;/* explorar la sublista a[0] a a[i] */

    for (j = 0; j < i; j++)/* intercambiar pareja y actualizar indiceIntercambio */

    if (a[j+1] < a[j]){

    long aux=a[j];a[j] = a[j+1];a[j+1] = aux;indiceIntercambio = j;

    }/* i se pone al valor del ndice del ltimo intercambio */

    i = indiceIntercambio;}

    }

    6.6.3. Anlisis del algoritmo de la burbujaCul es la eficiencia del algoritmo de ordenacin de la burbuja? Depender de la versin utilizada.En la versin ms simple se hacen n 1 pasadas y n 1 comparaciones en cada pasada. Porconsiguiente, el nmero de comparaciones es (n 1) * (n 1) = n2 2n + 1, es decir, la complejidades 0(n2).

    Si se tienen en cuenta las versiones mejoradas haciendo uso de las variables interruptor oindiceIntercambio, entonces se tendr una eficiencia diferente a cada algoritmo. En el mejor delos casos, la ordenacin de burbuja hace una sola pasada en el caso de una lista que ya est ordenadaen orden ascendente y por tanto su complejidad es 0(n). En el caso peor se requieren (n i 1)comparaciones y (n i 1) intercambios. La ordenacin completa requiere n(n 1)

    2comparaciones

    Algoritmos de ordenacin y bsqueda 177

  • y un nmero similar de intercambios. La complejidad para el caso peor es 0(n2) comparaciones y0(n2) intercambios. De cualquier forma, el anlisis del caso general es complicado dado que algunade las pasadas pueden no realizarse. Se podra sealar, entonces, que el nmero medio de pasadas ksea 0(n) y el nmero total de comparaciones es 0(n2). En el mejor de los casos, la ordenacin porburbuja puede terminar en menos de n 1 pasadas pero requiere, normalmente, muchos ms inter-cambios que la ordenacin por seleccin y su prestacin media es mucho ms lenta, sobre todocuando los arrays a ordenar son grandes.

    6.7. ORDENACIN SHELLLa ordenacin Shell debe el nombre a su inventor, D. L. Shell. Se suele denominar tambin orde-nacin por insercin con incrementos decrecientes. Se considera que el mtodo Shell es una mejorade los mtodos de insercin directa.

    En el lgoritmo de insercin, cada elemento se compara con los elementos contiguos de suizquierda, uno tras otro. Si el elemento a insertar es el ms pequeo hay que realizar muchascomparaciones antes de colocarlo en su lugar definitivo.

    El algoritmo de Shell modifica los saltos contiguos resultantes de las comparaciones por saltosde mayor tamao y con ello se consigue que la ordenacin sea ms rpida. Generalmente se tomacomo salto inicial n/2 (siendo n el nmero de elementos), luego se reduce el salto a la mitad en cadarepeticin hasta que el salto es de tamao 1. El Ejemplo 6.1 ordena una lista de elementos siguiendopaso a paso el mtodo de Shell.

    Ejemplo 6.1Obtener las secuencias parciales del vector al aplicar el mtodo Shell para ordenar en ordencreciente la lista:

    6 1 5 2 3 4 0

    El nmero de elementos que tiene la lista es 6, por lo que el salto inicial es 6/2 = 3. La siguientetabla muestra el nmero de recorridos realizados en la lista con los saltos correspondiente.

    Recorrido Salto Intercambios Lista1 3 (6,2),(5,4),(6,0) 2 1 4 0 3 5 62 3 (2, 0) 0 1 4 2 3 5 63 3 ninguno 0 1 4 2 3 5 6

    salto 3/2 = 14 1 (4,2),(4,3) 0 1 2 3 4 5 65 1 ninguno 0 1 2 3 4 5 6

    6.7.1. Algoritmo de ordenacin Shell

    Los pasos a seguir por el algoritmo para una lista de n elementos son:

    1. Dividir la lista original en n/2 grupos de dos, considerando un incremento o salto entre loselementos de n/2.

    2. Clarificar cada grupo por separado, comparando las parejas de elementos, y si no estnordenados, se intercambian.

    178 Algoritmos y estructuras de datos

  • 3. Se divide ahora la lista en la mitad de grupos (n/4), con un incremento o salto entre loselementos tambin mitad (n/4), y nuevamente se clasifica cada grupo por separado.

    4. As sucesivamente, se sigue dividiendo la lista en la mitad de grupos que en el recorridoanterior con un incremento o salto decreciente en la mitad que el salto anterior, y luegoclasificando cada grupo por separado.

    5. El algoritmo termina cuando se consigue que el tamao del salto es 1.Por consiguiente, los recorridos por la lista est condicionados por el bucle,

    intervalo v n / 2mientras (intervalo > 0) hacer

    Para dividir la lista en grupos y clasificar cada grupo se anida este cdigo,

    desde i v (intervalo + 1) hasta n hacerj v i - intervalo

    mientras (j > 0) hacerk v j + intervalosi (a[j] 0.

    6.7.2. Codificacin en C del algoritmo del mtodo Shell

    Al codificar en C este mtodo de ordenacin se ha de tener en cuenta que el operador, /, realiza unadivisin entera si los operandos son enteros, y esto es importante al calcular el ancho del salto entrepares de elementos: intervalo = n/2.

    En cuanto a los ndices, C toma como base el ndice 0 y, por consiguiente, se ha de desplazaruna posicin a la izquierda las variables ndice respecto a lo expuesto en el algoritmo.

    void ordenacionShell(double a[], int n){

    int intervalo, i, j, k;

    intervalo = n / 2;while (intervalo > 0){

    Algoritmos de ordenacin y bsqueda 179

  • for (i = intervalo; i < n; i++){

    j = i - intervalo;while (j >= 0){

    k = j + intervalo;if (a[j]

  • Ejemplo 6.2Se ordena una lista de nmeros enteros aplicando el algoritmo quicksort, como pivote se elige elprimer elemento de la lista.

    1. Lista original 5 2 1 7 9 3 8 7

    pivote elegido 5

    sublista izquierda1 (elementos menores que 5) 2 1 3

    sublista derecha1 (elementos mayores o iguales a 5) 9 8 72. El algoritmo se aplica a la sublista izquierda

    Sublista Izda1 2 1 3 sublista Izda 1

    pivote sublista Dcha 3

    Sublista Izda1 Izda pivote Dcha

    1 2 3

    3. El algoritmo se aplica a la sublista derechaSublista Dcha1 9 8 7

    sublista Izda 7 8pivote sublista Dcha

    Sublista Dcha1 Izda pivote Dcha

    7 8 9

    4. Lista ordenada finalSublista izquierda pivote Sublista derecha

    1 2 3 5 7 8 9

    Para recordarEl algoritmo quicksort requiere una estrategia de particin y la seleccin idnea del pivote.Las etapas fundamentales del algoritmo dependen del pivote elegido aunque la estrategiade particin suele ser similar.

    6.8.1. Algoritmo quicksort

    La primera etapa en el algoritmo de particin es obtener el elemento pivote; una vez que se haseleccionado se ha de buscar el sistema para situar en la sublista izquierda todos los elementos

    Algoritmos de ordenacin y bsqueda 181

  • menores que el pivote y en la sublista derecha todos los elementos mayores que el pivote. Suponga-mos que todos los elementos de la lista son distintos, aunque ser preciso tener en cuenta los casosen que existan elementos idnticos. En el Ejemplo 6.3 se elige como pivote el elemento central de lalista actual.

    Ejemplo 6.3Ordenar una lista de nmeros enteros aplicando el algoritmo quicksort, como pivote se elige elelemento central de la lista.

    Lista original: 8 1 4 9 6 3 5 2 7 0Pivote (elemento central) 6

    La etapa 2 requiere mover todos los elementos menores al pivote a la parte izquierda del array ylos elementos mayores a la parte derecha. Para ello se recorre la lista de izquierda a derecha utili-zando un ndice i que se inicializa en la posicin ms baja (inferior) buscando un elementomayor al pivote. Tambin se recorre la lista de derecha a izquierda buscando un elemento menor.Para hacer esto se utilizar un ndice j inicializado en la posicin ms alta (superior).

    El ndice i se detiene en el elemento 8 (mayor que el pivote) y el ndice j se detiene en elelemento 0 (menor que el pivote).

    8 1 4 9 6 3 5 2 7 0

    n i j v

    Ahora se intercambian 8 y 0 para que estos dos elementos se siten correctamente en cadasublista; y se incrementa el ndice i, y se decrementa j para seguir los intercambios.

    0 1 4 9 6 3 5 2 7 8

    i j

    A medida que el algoritmo contina, i se detiene en el elemento mayor, 9, y j se detiene en elelemento menor, 2.

    0 1 4 9 6 3 5 2 7 8

    i j

    Se intercambian los elementos mientras que i y j no se crucen. En caso contrario se detiene estebucle. En el caso anterior se intercambian 9 y 2.

    0 1 4 2 6 3 5 9 7 8

    i j

    Contina la exploracin y ahora el contador i se detiene en el elemento 6 (que es el pivote) y elndice j se detiene en el elemento menor 5.

    0 1 4 2 5 3 6 9 7 8

    ij

    182 Algoritmos y estructuras de datos

  • Los ndices tienen actualmente los valores i = 5, j = 5. Contina la exploracin hasta quei>j, acaba con i = 6, j = 5.

    0 1 4 2 5 3 6 9 7 8

    bbbbbnvbbbbbj i

    En esta posicin los ndices i y j han cruzado posiciones en el array y en este caso se detiene labsqueda y no se realiza ningn intercambio ya que el elemento al que accede j est ya correctamentesituado. Las dos sublistas ya han sido creadas, la lista original se ha dividido en dos particiones:

    sublista_izquierda pivote sublista_derecha

    0 1 4 2 5 3 6 9 7 8

    El primer problema a resolver en el diseo del algoritmo de quicksort es seleccionar el pivote.Aunque la posicin del pivote, en principio, puede ser cualquiera, una de las decisiones ms ponde-radas es aquella que considera el pivote como el elemento central o prximo al central de la lista. LaFigura 6.2 muestra las operaciones del algoritmo para ordenar la lista a[] de n elementos enteros.

    248446768575658899152179

    65

    7984997685758846152124

    21

    7984998885

    79848885

    75462415

    46

    76

    2415 75 99

    46 . . .

    24, 21, 15, 466588, 75, 85, 76, 99, 84, 79

    Izquierda:Pivote:

    Derecha:

    Figura 6.2. Ordenacin rpida eligiendo como pivote el elemento central.

    Los pasos que sigue el algoritmo quicksort:

    Seleccionar el elemento central de a[0:n-1] como pivote

    Algoritmos de ordenacin y bsqueda 183

  • Dividir los elementos restantes en particiones izquierda y derecha, de modoque ningn elemento de la izquierda tenga una clave (valor) mayor que el pivote y queningn elemento a la derecha tenga una clave ms pequea que la del pivote.

    Ordenar la particin izquierda utilizando quicksort recursivamente.

    Ordenar la particin derecha utilizando quicksort recursivamente.

    La solucin es particin izquierda seguida por el pivote y a continua-cin particin derecha.

    6.8.2. Codificacin en C del algoritmo quicksort

    La funcin quicksort() refleja el algoritmo citado anteriormente; esta funcin se llama pasandocomo primer argumento el array a[] y los ndices que le delimitan 0 y n-1 (ndice inferior ysuperior). La llamada a la funcin:

    quicksort(a, 0, n-1);

    y la codificacin recursiva de la funcin:

    void quicksort(double a[], int primero, int ultimo){

    int i, j, central;double pivote;

    central = (primero + ultimo)/2;pivote = a[central];i = primero;j = ultimo;

    do {while (a[i] < pivote) i++;while (a[j] > pivote) j--;

    if (i

  • 6.8.3. Anlisis del algoritmo quicksort

    El anlisis general de la eficiencia de quicksort es difcil. La mejor forma de ilustrar y calcular lacomplejidad del algoritmo es considerar el nmero de comparaciones realizadas teniendo en cuentacircunstancias ideales. Supongamos que n (nmero de elementos de la lista) es una potencia de 2,n = 2k (k = log2 n). Adems, supongamos que el pivote es el elemento central de cada lista, de modoque quicksort divide la sublista en dos sublistas aproximadamente iguales.

    En la primera exploracin o recorrido hay n 1 comparaciones. El resultado de la etapa creados sublistas aproximadamente de tamao n/2. En la siguiente fase, el proceso de cada sublista re-quiere aproximadamente n/2 comparaciones. Las comparaciones totales de esta fase son 2(n/2) = n.La siguiente fase procesa cuatro sublistas que requieren un total de 4(n/4) comparaciones, etc.Eventualmente, el proceso de divisin termina despus de k pasadas cuando la sublista resultantetenga tamao 1. El nmero total de comparaciones es aproximadamente:

    n + 2(n/2) + 4(n/4) + + n(n/n) = n + n + + n= n k = n log2 n

    Para una lista normal la complejidad de quicksort es O(n log2 n). El caso ideal que se haexaminado se realiza realmente cuando la lista (el array) est ordenado en orden ascendente. Eneste caso el pivote es precisamente el centro de cada sublista.

    15 25 35 40 50 55 65 75

    pivote

    Si el array est en orden ascendente, el primer recorrido encuentra el pivote en el centro de lalista e intercambia cada elemento en las sublistas inferiores y superiores. La lista resultante est casiordenada y el algoritmo tiene la complejidad O(n log2 n).

    El escenario del caso peor de quicksort ocurre cuando el pivote cae consistentemente en unasublista de un elemento y deja el resto de los elementos en la segunda sublista. Esto sucede cuandoel pivote es siempre el elemento ms pequeo de su sublista. En el recorrido inicial, hay n compara-ciones y la sublista grande contiene n 1 elementos. En el siguiente recorrido, la sublista mayorrequiere n 1 comparaciones y produce una sublista de n 2 elementos, etc. El nmero total decomparaciones es:

    n + n 1 + n 2 + + 2 = (n 1)(n + 2)/2La complejidad es O(n2). En general el algoritmo de ordenacin tiene como complejidad media

    O(n log2 n) siendo posiblemente el algoritmo ms rpido. La Tabla 6.1 muestra las complejidadesde los algoritmos empleados en los mtodos explicados en el libro.

    Tabla 6.1. Comparacin de complejidad en mtodos de ordenacinMtodo ComplejidadBurbuja n2Insercin n2Seleccin n2Montculo n log2 nFusin n log2 nShell n log2 nQuicksort n log2 n

    Algoritmos de ordenacin y bsqueda 185

  • En conclusin, se suele recomendar que para listas pequeas los mtodos ms eficientes soninsercin y seleccin; y para listas grandes, el quicksort. El algoritmo de Shell suele variar muchosu eficiencia en funcin de la variacin del nmero de elementos por lo que es ms difcil que en losotros mtodos proporcionar un consejo eficiente. Los mtodos de fusin y por montculo suelen sermuy eficientes para listas muy grandes.

    El mtodo de ordenacin por montculos, tambin llamado Heapsort, se desarrolla ms adelan-te, en el Captulo 12, Colas de prioridades y montculos, al ser una aplicacin de la estructuramontculo.

    6.9. ORDENACIN BINSORT Y RADIXSORTEstos mtodos de ordenacin utilizan urnas para depositar en ellas los registros en el proceso deordenacin. En cada recorrido de la lista se depositan en una urnai aquellos registros cuya clavetienen una cierta correspondencia con i.

    6.9.1. Mtodo de Binsort

    Este mtodo, tambin llamado clasificacin por urnas, persigue conseguir funciones de tiempo deejecucin menores de O(n log n), para ordenar una secuencia de n elementos siempre que seconozca algo acerca del tipo de las claves por las que se estn ordenando.

    Supngase que se tiene un vector v[] de registros, se quiere ordenar respecto un campo clavede tipo entero, adems se sabe que los valores de las claves se encuentran en el rango de 1 a n, sinclaves duplicadas y siendo n el nmero de elementos. En estas circunstancias es posible colocar losregistros ordenados en un array auxiliar t[] mediante este bucle:

    for 1:= 1 to n dot[v[i].clave] = v[i];

    Sencillamente determina la posicin que le corresponde segn el valor del campo clave. Elbucle lleva un tiempo de ejecucin de complejidad O(n).

    Esta ordenacin tan sencilla que se ha expuesto es un caso particular del mtodo de ordenacinpor urnas (binsort). Este mtodo utiliza urnas, cada urna contiene todos los registros con una mismaclave.

    El proceso consiste en examinar cada registro r a clasificar y situarle en la urna i, coincidiendoi con el valor del campo clave de r. En la mayora de los casos en que se utilice el algoritmo, sernecesario guardar ms de un registro en una misma urna por tener claves repetidas. Entonces estasurnas hay que concatenarlas en el orden de menor ndice de urna a mayor, as quedar el array enorden creciente respecto al campo clave.

    En la Figura 6.3 se muestra un vector de m urnas. Las urnas estn representadas por listasenlazadas.

    1

    2

    R1

    R2

    R3

    Rm

    R1

    R2

    R3

    Rm

    R1

    R2

    R3

    Rm...

    ...

    ...

    ...

    Urnas

    m

    Figura 6.3. Estructura formada por m urnas.

    186 Algoritmos y estructuras de datos

  • Algoritmo de ordenacin BinsortSe considera que el campo clave de los registros que se van a ordenar son nmeros enteros en elrango 1 .. m. Son necesarias m urnas por lo que es necesario definir un vector de m urnas. Las urnaspueden ser representadas por listas enlazadas, cada elemento de la lista contiene un registro cuyocampo clave es el correspondiente al de la urna en la que se encuentra. As en la urna 1 se sitan losregistros cuyo campo clave sea igual a 1, en la urna 2 los registros cuyo campo clave sea 2, y assucesivamente en la urna i se sitan los registros cuyo campo clave sea igual a i.

    Una vez que se hayan distribuido los registros en las diversas urnas es necesario concatenar laslistas. En la Figura 6.4 se muestra cmo realizar la concatenacin.

    R1

    R2

    R3

    R1

    R2

    R3

    R1

    R2

    R3

    ...

    ...

    ...

    Rm Rm Rm...

    Figura 6.4. Concatenacin de urnas representadas por listas enlazadas.

    Los pasos que sigue el algoritmo expresado en pseudocdigo para un vector de n registros:

    OrdenacionBinsort(vector, n)

    inicioCrearUrnas(Urnas);

    {Distribucin de registros en sus correspondientes urnas}desde j = 1 hasta n hacer

    AadirEnUrna(Urnas[vector[j].clave], vector[j]);fin_desde

    {Concatena las listas que representan a las urnasdesde Urnai hasta Urnam}

    i = 1; {bsqueda de primera urna no vaca}mientras EstaVacia(Urnas[i]) hacer

    i = i+1fin_mientras

    desde j = i+l a m hacerEnlazarUrna(Urnas[i], Urnas[j]);

    fin_desde

    {Se recorre la lista-urna resultante de la concatenacin}j = 1;dir = ;mientras dir nulo hacer

    vector[j] = ;j = j+i;dir = Sgte(dir)

    fin_mientras

    fin

    Algoritmos de ordenacin y bsqueda 187

  • 6.9.2. Mtodo de Radixsort

    Este mtodo puede considerarse como una generalizacin de la clasificacin por urnas. Aprovechala estrategia de la forma ms antigua de clasificacin manual, consistente en hacer diversos monto-nes de fichas, cada uno caracterizado por tener sus componentes un mismo dgito (letra, si esalfabtica) en la misma posicin; estos montones se recogen en orden ascendente y se reparte denuevo en montones segn el siguiente dgito de la clave.

    Como ejemplo, suponer que se han de ordenar estas fichas identificadas por tres dgitos:

    345, 721, 425, 572, 836, 467, 672,194, 365, 236, 891, 746, 431, 834, 247, 529, 216, 389

    Atendiendo al dgito de menor peso (unidades) las fichas se distribuyen en montones del 0 al 9;

    431 672 999 999 216431 365 746891 672 834 425 236 247 389721 572 194 345 836 467 5291 2 4 5 6 7 9

    Recogiendo los montones en orden, la secuencia de fichas queda:

    721, 891, 431, 572, 672, 194, 834, 345, 425, 365, 836, 236, 746, 216, 467, 247, 529, 389

    De esta secuencia podemos decir que est ordenada respecto al dgito de menor peso, respecto alas unidades. Pues bien, ahora de nuevo se distribuye la secuencia de fichas en montones respecto alsegundo dgito:

    236529 836 247425 834 746 467 672 194

    216 721 431 345 365 572 389 8911 2 3 4 6 7 8 9

    Recogiendo de nuevo los montones en orden, la secuencia de fichas queda:

    216, 721, 425, 529, 431, 834, 836, 236, 345, 746, 247, 365, 467, 572, 672, 389, 891, 194

    En este momento esta secuencia de fichas ya estn ordenadas respecto a los dos ltimos dgitos,es decir, respecto a las decenas. Por ltimo, se distribuye las fichas en montones respecto al tercerdgito:

    247 389 467 891236 365 431 572 746 836

    194 216 345 425 529 672 721 8341 2 3 4 5 6 7 8

    Recogiendo de nuevo los montones en orden, la secuencia de fichas queda ya ordenada:

    194, 216, 236, 247, 345, 365, 389, 425, 431, 467, 529, 572, 672, 121, 746, 834, 836, 891

    188 Algoritmos y estructuras de datos

  • Algoritmo de ordenacin RadixsortLa idea clave de la ordenacin Radixsort (tambin llamada por residuos) es clasificar por ur-nas primero respecto al dgito de menor peso (menos significativo) dk, despus concatenar lasurnas, clasificar de nuevo respecto al siguiente dgito dk1, y as sucesivamente se sigue con elsiguiente dgito hasta alcanzar el dgito ms significativo dl, en ese momento la secuencia estarordenada. La concatenacin de las urnas consiste en enlazar el final de una con el frente de lasiguiente.

    Al igual que en el mtodo de Binsort, las urnas se representan mediante un vector de listas. En elcaso de que la clave respecto a la que se ordena sea un entero, se tendrn 10 urnas, numeradas de 0a 9. Si la clave respecto a la que se ordena es alfabtica, habr tantas urnas como letras distintas,desde la urna que represente a la letra a hasta la z.

    Para el caso de que clave sea entera, en primer lugar se determina el mximo nmero de dgitosque puede tener la clave. En un bucle de tantas iteraciones como mximo de dgitos se realizan lasacciones de distribuir por urnas los registros, concatenar...

    La distribucin por urnas exige obtener el dgito del campo clave que se encuentra en la posi-cin definida por el bucle externo, dicho dgito ser el ndice de la urna.

    OrdenacionRadixsort(vector, n)

    inicio

    < clculo el nmero mximo de dgitos: ndig >

    peso = 1 { permite obtener los dgitos de menor a mayor peso}desde i = 1 hasta ndig hacer

    CrearUrnas(Urnas);desde j = 1 hasta n hacer

    d = (vector[j] / peso) modulo 10;AadirEnUma(Urnas[d], vector[j]);

    fin_desde

    < bsqueda de primera urna no vaca: j >

    desde r = j+1 hasta M hace { M: nmero de urnas }EnlazarUma(Urnas[r], Urnas[j]);

    fin_desde

    {Se recorre la lsta-urna resultante de la concatenacin}r = 1;dir = frente(Urna[j]);mientras dir nulo hacer

    vector[r] = dir.registro;r = r+1;dir = siguiente(dir)

    end

    peso = peso * 10;fin_desde

    fin_ordenacion

    Algoritmos de ordenacin y bsqueda 189

  • 6.10. BSQUEDA EN LISTAS: BSQUEDAS SECUENCIAL Y BINARIACon mucha frecuencia los programadores trabajan con grandes cantidades de datos almacenados enarrays y registros, y por ello ser necesario determinar si un array contiene un valor que coincidacon un cierto valor clave. El proceso de encontrar un elemento especfico de un array se denominabsqueda. En esta seccin se examinarn dos tcnicas de bsqueda: bsqueda lineal o secuencial,la tcnica ms sencilla, y bsqueda binaria o dicotmica, la tcnica ms eficiente.

    6.10.1. Bsqueda secuencial

    La bsqueda secuencial busca un elemento de una lista utilizando un valor destino llamado clave.En una bsqueda secuencial (a veces llamada bsqueda lineal), los elementos de una lista o vectorse exploran (se examinan) en secuencia, uno despus de otro. La bsqueda secuencial es necesaria,por ejemplo, si se desea encontrar la persona cuyo nmero de telfono es 958-220000 en un directo-rio o listado telefnico de su ciudad. Los directorios de telfonos estn organizados alfabticamentepor el nombre del abonado en lugar de por nmeros de telfono, de modo que deben explorarsetodos los nmeros, uno despus de otro, esperando encontrar el nmero 958-220000.

    El algoritmo de bsqueda secuencial compara cada elemento del array con la clave de bsque-da. Dado que el array no est en un orden prefijado, es probable que el elemento a buscar pueda serel primer elemento, el ltimo elemento o cualquier otro. De promedio, al menos el programa tendrque comparar la clave de bsqueda con la mitad de los elementos del array. El mtodo de bsquedalineal funcionar bien con arrays pequeos o no ordenados. La eficiencia de la bsqueda secuenciales pobre, tiene complejidad lineal, O(n).

    6.10.2. Bsqueda binaria

    La bsqueda secuencial se aplica a cualquier lista. Si la lista est ordenada, la bsqueda binariaproporciona una tcnica de bsqueda mejorada. Una bsqueda binaria tpica es la bsqueda de unapalabra en un diccionario. Dada la palabra, se abre el libro cerca del principio, del centro o del finaldependiendo de la primera letra del primer apellido o de la palabra que busca. Se puede tener suertey acertar con la pgina correcta; pero, normalmente, no ser as y se mueve el lector a la pginaanterior o posterior del libro. Por ejemplo, si la palabra comienza con J y se est en laL se mueve uno hacia atrs. El proceso contina hasta que se encuentra la pgina buscada o hastaque se descubre que la palabra no est en la lista.

    Una idea similar se aplica en la bsqueda en una lista ordenada. Se sita la lectura en el centrode la lista y se comprueba si la clave coincide con el valor del elemento central. Si no se encuentrael valor de la clave, se sigue la bsqueda uno en la mitad inferior o superior del elemento central dela lista. En general, si los datos de la lista estn ordenados se puede utilizar esa informacin paraacortar el tiempo de bsqueda.

    Ejemplo 6.4Se desea buscar el elemento 225 y ver si se encuentra en el conjunto de datos siguiente:

    a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]13 44 75 100 120 275 325 510

    190 Algoritmos y estructuras de datos

  • El punto central de la lista es el elemento a[3] (100). El valor que se busca es 225, mayor que100; por consiguiente, la bsqueda contina en la mitad superior del conjunto de datos de la lista, esdecir, en la sublista,

    a[4] a[5] a[6] a[7]120 275 325 510

    Ahora el elemento mitad de esta sublista a[5] (275). El valor buscado, 225, es menor que275 y, por consiguiente, la bsqueda contina en la mitad inferior del conjunto de datos de la listaactual; es decir, en la sublista de un nico elemento:

    a[4]120

    El elemento mitad de esta sublista es el propio elemento a[4] (120). Al ser 225 mayor que120, la bsqueda debe continuar en una sublista vaca. Se concluye indicando que no se ha encon-trado la clave en la lista.

    6.10.3. Algoritmo y codificacin de la bsqueda binaria

    Suponiendo que la lista est almacenada como un array, los ndices de la lista son: bajo = 0y alto = n-1 y n es el nmero de elementos del array, los pasos a seguir:

    1. Calcular el ndice del punto central del array

    central = (bajo + alto)/2 (divisin entera)

    2. Comparar el valor de este elemento central con la clave:

    clave clave clave|bbbbbb|bbbbbb| |bbbbbb|bbbbbb| |bbbbbb|bbbbbb|bajo central alto bajo central alto bajo central alto

    Clave encontrada Bsqueda lista inferior Bsqueda lista superior

    Figura 6.5. Bsqueda binaria de un elemento.

    Si a[central] < clave, la nueva sublista de bsqueda tiene por valores extremos desu rango bajo = central+1..alto.

    Si clave < a[central], la nueva sublista de bsqueda tiene por valores extremos de surango bajo..central-1.

    clave clave[bbbbbbbbbb] [bbbbbbbbbb]bajo central 1 = alto bajo = central + 1 alto

    El algoritmo se termina bien porque se ha encontrado la clave o porque el valor de bajo excedea alto y el algoritmo devuelve el indicador de fallo de 1 (bsqueda no encontrada).

    Algoritmos de ordenacin y bsqueda 191

  • Ejemplo 6.5Sea el array de enteros A (-8, 4, 5, 9, 12, 18, 25, 40, 60), buscar la clave, clave = 40.

    1. a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8]

    8 4 5 9 12 18 25 40 60 bajo = 0alto = 8

    central

    central =bajo + alto

    2=

    0 + 82

    = 4

    clave (40) > a[4] (12)

    2. Buscar en sublista derecha

    18 25 40 60 bajo = 5alto = 8

    central =bajo + alto

    2=

    5 + 82

    = 6 (divisin entera)clave (40) > a[6] (25)

    3. Buscar en sublista derecha

    40 60 bajo = 7alto = 8

    central =bajo + alto

    2=

    7 + 82

    = 7

    clave (40) = a[7] (40) (bsqueda con xito)

    4. El algoritmo ha requerido 3 comparaciones frente a 8 comparaciones (n 1, 9 1 = 8) que sehubieran realizado con la bsqueda secuencial.

    La codificacin del algoritmo de bsqueda binaria:

    /*bsqueda binaria.devuelve el ndice del elemento buscado, o bien -1 caso de fallo

    */

    int busquedaBin(int lista[], int n, int clave){

    int central, bajo, alto;int valorCentral;

    bajo = 0;alto = n-1;while (bajo

  • {central = (bajo + alto)/2; /* ndice de elemento central */valorCentral = lista[central]; /* valor del ndice central */if (clave == valorCentral)

    return central; /* encontrado, devuelve posicin */else if (clave < valorCentral)

    alto = central -1; /* ir a sublista inferior */else

    bajo = central + 1; /* ir a sublista superior */}return -1; /* elemento no encontrado */

    }

    6.10.4. Anlisis de los algoritmos de bsqueda

    Al igual que sucede con las operaciones de ordenacin cuando se realizan operaciones de bsquedaes preciso considerar la eficiencia (complejidad) de los algoritmos empleados en la bsqueda. Elgrado de eficiencia en una bsqueda ser vital cuando se trata de localizar una informacin en unalista o tabla en memoria, o bien en un archivo de datos.

    Complejidad de la bsqueda secuencialLa complejidad de la bsqueda secuencial diferencia entre el comportamiento en el caso peor ymejor. El mejor caso se encuentra cuando aparece una coincidencia en el primer elemento de la listay en ese caso el tiempo de ejecucin es O(1). El caso peor se produce cuando el elemento no est enla lista o se encuentra al final de la lista. Esto requiere buscar en todos los n trminos, lo que implicauna complejidad de O(n).

    El caso medio requiere un poco de razonamiento probabilista. Para el caso de una lista aleatoriaes probable que una coincidencia ocurra en cualquier posicin. Despus de la ejecucin de unnmero grande de bsquedas, la posicin media para una coincidencia es el elemento central n/2. Elelemento central ocurre despus de n/2 comparaciones, que define el coste esperado de la bsqueda.Por esta razn, se dice que la prestacin media de la bsqueda secuencial es O(n).

    Anlisis de la bsqueda binariaEl caso mejor se presenta cuando una coincidencia se encuentra en el punto central de la lista. Eneste caso la complejidad es O(1) dado que slo se realiza una prueba de comparacin de igualdad.La complejidad del caso peor es O(log2 n) que se produce cuando el elemento no est en la lista o elelemento se encuentra en la ltima comparacin. Se puede deducir intuitivamente esta complejidad.El caso peor se produce cuando se debe continuar la bsqueda y llegar a una sublista de longi-tud de 1. Cada iteracin que falla debe continuar disminuyendo la longitud de la sublista por unfactor de 2. El tamao de las sublistas es:

    n n/2 n/4 n/8 . . . 1

    La divisin de sublistas requiere m iteraciones, en cada iteracin el tamao de la sublista sereduce a la mitad. La sucesin de tamaos de las sublistas hasta una sublista de longitud 1:

    n n/2 n/2 n/23 n/24 . . . n/2m

    siendo n/2m = 1.

    Algoritmos de ordenacin y bsqueda 193

  • Tomando logaritmos en base 2 en la expresin anterior quedar:

    n = 2mm = log2 n

    Por esa razn la complejidad del caso peor es O(log2 n). Cada iteracin requiere una operacinde comparacin:

    Total comparaciones ] 1 + log2 n

    Comparacin de la bsqueda binaria y secuencialLa comparacin en tiempo entre los algoritmos de bsqueda secuencial y binaria se va haciendoespectacular a medida que crece el tamao de la lista de elementos. Tengamos presente que en elcaso de la bsqueda secuencial, en el peor de los casos, coincidir el nmero de elementos examina-dos con el nmero de elementos de la lista tal como representa su complejidad O(n).

    Sin embargo, en el caso de la bsqueda binaria, tengamos presente, por ejemplo, que 210 = 1.024,lo cual implica el examen de 11 posibles elementos; si se aumenta el nmero de elementos de unalista a 2.048 y teniendo presente que 211 = 2.048 implicar que el nmero mximo de elementosexaminados en la bsqueda binaria es 12. Si se sigue este planteamiento, se puede encontrar elnmero m ms pequeo para una lista de 1.000.000, tal que

    2n 1.000.000

    Es decir, 219 = 524.288, 220 = 1.048.576 y por tanto el nmero de elementos examinados (en elpeor de los casos) es 21.

    La Tabla 6.2 muestra la comparacin de los mtodos de bsqueda secuencial y bsqueda bina-ria. En la misma tabla se puede apreciar una comparacin del nmero de elementos que se debenexaminar utilizando bsquedas secuencial y binaria. Esta tabla muestra la eficiencia de la bsquedabinaria comparada con la bsqueda secuencial y cuyos resultados de tiempo vienen dados por lasfunciones de complejidad O(log2 n) y O(n) de las bsquedas binaria y secuencial respectivamente.

    Tabla 6.2. Comparacin de las bsquedas binaria y secuencial

    Nmeros de elementos examinados

    Tamao de la lista Bsqueda binaria Bsqueda secuencial

    1 1 110 4 101.000 11 1.0005.000 14 5.000100.000 18 100.0001.000.000 21 1.000.000

    A tener en cuentaLa bsqueda secuencial se aplica para localizar una clave en un vector no ordenado. Paraaplicar el algoritmo de bsqueda binaria la lista, o vector, donde se busca debe de estarordenado.

    La complejidad de la bsqueda binaria es logartmica, O(log n), ms eficiente que labsqueda secuencial que tiene complejidad lineal, O(n).

    194 Algoritmos y estructuras de datos

  • RESUMEN Una de las aplicaciones ms frecuentes en programacin es la ordenacin. Existen dos tcnicas de ordenacin fundamentales en gestin de datos: ordenacin de listas y ordena-

    cin de archivos. Los datos se pueden ordenar en orden ascendente o en orden descendente. Cada recorrido de los datos durante el proceso de ordenacin se conoce como pasada o iteracin. Los algoritmos de ordenacin bsicos son:

    Seleccin. Insercin. Burbuja.

    Los algoritmos de ordenacin ms avanzados son:

    Shell. Mergesort. Radixsort. Binsort. Quicksort.

    La eficiencia de los algoritmos de burbuja, insercin y seleccin es O(n2). La eficiencia de los algoritmos, radixsort, mergesort y quicksort es O(n log n). La bsqueda es el proceso de encontrar la posicin de un elemento destino dentro de una lista Existen dos mtodos bsicos de bsqueda en arrays: secuencial y binaria. La bsqueda secuencial se utiliza normalmente cuando el array no est ordenado. Comienza en el

    principio del array y busca hasta que se encuentra el dato buscado y se llega al final de la lista. Si un array est ordenado, se puede utilizar un algoritmo ms eficiente denominado bsqueda

    binaria. La eficiencia de una bsqueda secuencial es O(n). La eficiencia de una bsqueda binaria es O(log n).

    EJERCICIOS6.1. Cul es la diferencia entre ordenacin por intercambio y ordenacin por el mtodo de la burbuja?

    6.2. Se desea eliminar todos los nmeros duplicados de una lista o vector (array). Por ejemplo, si el arraytoma los valores

    4 7 11 4 9 5 11 7 3 5

    ha de cambiarse a

    4 7 11 9 5 3

    Escribir una funcin que elimine los elementos duplicados de un array.

    6.3. Escribir una funcin que elimine los elementos duplicados de un vector ordenado. Cul es laeficiencia de esta funcin? Comparar la eficiencia con la correspondiente a la funcin del Ejerci-cio 6.2.

    6.4. Un vector contiene los elementos mostrados a continuacin. Los primeros dos elementos se hanordenado utilizando un algoritmo de insercin. Cul ser el valor de los elementos del vectordespus de tres pasadas ms del algoritmo?

    3 13 8 25 45 23 98 58

    Algoritmos de ordenacin y bsqueda 195

  • 6.5. Se tiene la siguiente lista:

    47 3 21 32 56 92

    Despus de dos pasadas de un algoritmo de ordenacin, el array se ha quedado dispuesto as:

    3 21 47 32 56 92

    Qu algoritmo de ordenacin se est utilizando (seleccin, burbuja o insercin)? Justifique larespuesta.

    6.6. Un array contiene los elementos indicados ms abajo. Utilizando el algoritmo de ordenacin Shellencuentre las pasadas y los intercambios que se realizan para su ordenacin.

    8 43 17 6 40 16 18 97 11 7

    6.7. Partiendo del mismo array que en el Ejercicio 6.6, encuentre las particiones e intercambios querealiza el algoritmo de ordenacin quicksort para su ordenacin.

    6.8. Un array de registros se quiere ordenar segn el campo clave fecha de nacimiento. Dicho campoconsta de tres subcampos: da, mes y ao de 2, 2 y 4 dgitos respectivamente. Adaptar el mtodo deordenacin Radixsort a esta ordenacin.

    6.9. Un array contiene los elementos indicados ms abajo. Utilizando el algoritmo de bsqueda binaria,trazar las etapas necesarias para encontrar el nmero 88.

    8 13 17 26 44 56 88 97

    Igual bsqueda pero aplicada al caso del nmero 20.

    6.10. Escribir la funcin de ordenacin correspondiente al mtodo Radixsort para poner en orden alfab-tico una lista de n nombres.

    6.11. Escribir una funcin de bsqueda binaria aplicado a un array ordenado en modo descendente.

    6.12. Supongamos que se tiene una secuencia de n nmeros que deben ser clasificados:

    1. Utilizar el mtodo de Shell para determinar cuntas comparaciones y cuntos intercambios serequieren para clasificar la secuencia si:

    Ya est clasificada. Est en orden inverso.

    2. Repetir el paso 1 para el mtodo de quicksort.

    PROBLEMAS6.1. Un mtodo de ordenacin muy simple, pero no muy eficiente, de elementos x1, x2, x3, ...

    xn en orden ascendente es el siguiente:Paso 1: Localizar el elemento ms pequeo de la lista x1 a xn; intercambiarlo con x1.Paso 2: Localizar el elemento ms pequeo de la lista x2 a xn, intercambiarlo con x2.Paso 3: Localizar el elemento ms pequeo de la lista x3 a xn, intercambiarlo con xn.En el ltimo paso, los dos ltimos elementos se comparan e intercambian, si es necesa-rio, y la ordenacin se termina. Escribir un programa para ordenar una lista de elemen-tos, siguiendo este mtodo.

    196 Algoritmos y estructuras de datos

  • 6.2. Dado un vector x de n elementos reales, donde n es impar, disear una funcin quecalcule y devuelva la mediana de ese vector. La mediana es el valor tal que la mitad delos nmeros son mayores que el valor y la otra mitad son menores. Escribir un progra-ma que compruebe la funcin.

    6.3. Se trata de resolver el siguiente problema escolar. Dadas las notas de los alumnos deun colegio en el primer curso de bachillerato, en las diferentes asignaturas (5, porcomodidad), se trata de calcular la media de cada alumno, la media de cada asignatura,la media total de la clase y ordenar los alumnos por orden decreciente de notas mediasindividuales.Nota: Utilizar como algoritmo de ordenacin el mtodo Shell.

    6.4. Escribir un programa de consulta de telfonos. Leer un conjunto de datos de mil nom-bres y nmeros de telfono de un archivo que contiene los nmeros en orden aleatorio.Las consultas han de poder realizarse por nombre y por nmero de telfono.

    6.5. Realizar un programa que compare el tiempo de clculo de las bsquedas secuencial ybinaria. Una lista A se rellena con 2.000 enteros aleatorios en el rango 0 ... 1.999 y acontinuacin se ordena. Una segunda lista B se rellena con 500 enteros aleatorios enel mismo rango. Los elementos de B se utilizan como claves de los algoritmos debsqueda.

    6.6. Se dispone de dos vectores, Maestro y Esclavo, del mismo tipo y nmero de elementos.Se deben imprimir en dos columnas adyacentes. Se ordena el vector Maestro, perosiempre que un elemento de Maestro se mueva, el elemento correspondiente de Escla-vo debe moverse tambin; es decir, cualquier cosa que se haga en Maestro[i] debehacerse en Esclavo[i]. Despus de realizar la ordenacin se imprimen de nuevo losvectores. Escribir un programa que realice esta tarea.Nota: Utilizar como algoritmo de ordenacin el mtodo quicksort.

    6.7. Cada lnea de un archivo de datos contiene informacin sobre una compaa de infor-mtica. La lnea contiene el nombre del empleado, las ventas efectuadas por el mismo yel nmero de aos de antigedad del empleado en la compaa. Escribir un programaque lea la informacin del archivo de datos y a continuacin se visualiza. La informacindebe ser ordenada por ventas de mayor a menor y visualizada de nuevo.

    6.8. Se desea realizar un programa que realice las siguientes tareas:

    a) Generar, aleatoriamente, una lista de 999 nmeros reales en el rango de 0 a20.000.

    b) Ordenar en modo creciente por el mtodo de la burbuja.c) Ordenar en modo creciente por el mtodo Shell.d Ordenar en modo creciente por el mtodo Radixsort.e) Buscar si existe el nmero x (ledo del teclado) en la lista. La bsqueda debe ser

    binaria.

    Ampliar el programa anterior de modo que se puedan obtener y visualizar en el progra-ma principal los siguientes tiempos:

    t1. Tiempo empleado en ordenar la lista por cada uno de los mtodos.t2. Tiempo que se empleara en ordenar la lista ya ordenada.t3. Tiempo empleado en ordenar la lista ordenada en orden inverso.

    6.9. Construir un mtodo que permita ordenar por fechas y de mayor a menor un vector den elementos que contiene datos de contratos (n 50). Cada elemento del vector debe

    Algoritmos de ordenacin y bsqueda 197

  • ser un objeto con los campos da, mes, ao y nmero de contrato. Pueden existir diver-sos contratos con la misma fecha, pero no nmeros de contrato repetidos.Nota: El mtodo a utilizar para ordenar ser el de radixsort.

    6.10. Escribir un programa que genere un vector de 10.000 nmeros aleatorios de 1 a 500.Realice la ordenacin del vector por dos mtodos: Binsort. Radixsort.Escribir el tiempo empleado en la ordenacin de cada mtodo.

    6.11. Se leen dos listas de nmeros enteros, A y B de 100 y 60 elementos, respectivamente.Se desea resolver mediante procedimientos las siguientes tareas:a) Ordenar aplicando el mtodo de quicksort cada una de las listas A y B.b) Crear una lista C por intercalacin o mezcla de las listas A y B.c) Visualizar la lista C ordenada.

    198 Algoritmos y estructuras de datos