You are on page 1of 17

Mtodos de ordenamiento y bsqueda Daniel Rodrguez Zepeta CC203 D01 Ordenamiento La ordenacin o clasificacin de datos (sort) es una operacin

consistente en disponer un conjunto estructura- de datos, en algn determinado orden con respecto a uno de los campos elementos del conjunto. Los elementos numricos se pueden ordenar en orden creciente o decreciente de acuerdo al valor numrico del elemento. En terminologa de ordenacin, el elemento por el cual esta ordenado un conjunto de datos se denomina clave. Una coleccin de datos puede ser almacenada en un archivo, un arreglo (vector o tabla), un arreglo de registros, una lista enlazada o un rbol. Cuando los datos estn almacenados en un arreglo, una lista enlazada o un rbol, se denomina ordenacin interna. Si los datos estn almacenados en un archivo el proceso de ordenacin se llama ordenacin externa. Los mtodos (algoritmos) de ordenacin son numerosos, por ello se debe prestar especial atencin en su eleccin Cmo se sabe cual es el mejor algoritmo? La eficiencia es el factor que mide la calidad y rendimiento de un algoritmo. 1. tiempo menor de ejecucin en computadora 2. menor nmero de instrucciones Los mtodos de ordenacin se suelen dividir en dos grandes grupos: directos indirectos(avanzados) burbuja, seleccin, insercin Shell, ordenacin rpida, ordenacin por mezcla

Ordenacin por burbuja Este mtodo es clsico y muy sencillo, aunque por desgracia poco eficiente. La ordenacin por burbuja se basa en la comparacin de elementos adyacentes de la lista (vector) e intercambiar sus valores si estn desordenados. De este modo se dice que los valores ms pequeos burbujean hacia la parte superior de la lista, mientras que los valores ms grandes se hunden haca el fondo de la lista.

Supongamos un vector A[1], A[2],...,A[n]. Se comienza el seguimiento del vector de izquierda a derecha, comparando A[1] con A[2]; si estn desordenados se intercambian entre s. A continuacin se compara A[2] con A[3], intercambindolos si estn desordenados, este proceso de comparaciones e intercambios continua a lo largo de toda la lista. Estas operaciones constituyen una pasada a travs de la lista. Al terminar esta pasada el elemento mayor est en la parte inferior y algunos de los elementos han burbujeado hacia arriba de la lista. Se vuelve a explorar de nuevo la lista comparando elementos consecutivos e intercambindolos cuando estn desordenados, pero esta vez el elemento mayor no se compara, ya que se encuentra en su posicin correcta, al terminar esta pasada se habr situado en su sitio el segundo elemento ms grande se siguen las comparaciones hasta que toda la lista este ordenada cosa que suceder cuando

se hayan realizado (n-1) pasadas. Para su mejor comprensin, veamos grficamente el proceso anterior con un vector (lista) con cinco elementos; A[1], A[2], A[3], A[4], A[5].

A[1] A[2] A[3] A[4] A[5]

23 19 45 31 15 Lista sin ordenar

15 19 23 31 44 Lista ordenada

En la lista A, i ser el nmero de la pasada y j indica el orden del elemento de la lista. Se compara el elemento j-esimo y el (j+1)-simo. Pasada 1: i=1 A[1] A[2] A[3] A[4] A[5] 23 19 45 31 15 j=1 19 23 45 31 15 j=2 19 23 45 31 15 j=3 19 23 31 45 15 j=4 19 23 31 15 45 elemento ordenado

Se han realizado cuatro comparaciones (5-1 o bien n-1 en el caso de n elementos) y tres intercambios.

Pasada 2: i = 2

A[1]
A[2] A[3] A[4] A[5]

19 23 31 15 45

19 23 31 15 45

19 23 31 15 45

19 23 15 31 45

19 23 15 31 45

J=1

j=2

j=3

j=4

Pasada 3: i = 3 elemento ordenado

A[1] A[2] A[3] A[4] A[5]

19 23 15 31 45 j=1

19 23 15 31 45 j=2

19 15 23 31 45 j=3

19 15 23 31 45 j=4

19 15 23 31 45 elemento ordenado

Pasada 4: i =4 A[1] 19 15 15 15 15

A[2]
A[3] A[4] A[5]

15
23 31 45 j=1

19
23 31 45 j=2

19
23 31 45 j=3

19
23 31 45 j=4

19
23 31 45 j=5 elemento ordenado

Se observa que se necesitan cuatro pasadas para ordenar una lista de nmeros de cinco elementos, por lo que una lista de n elementos necesitar n-1 pasadas. El nmero de pasadas se puede controlar con un bucle for y cada secuencia de comparaciones se puede controlar con un bucle for anidado al bucle de pasadas, en el que j vara desde 1 hasta 5 menos el valor especifico de i.

Algoritmo (Pseudocdigo) Desde i = 1hasta n-1 hacer Desde j= 1 hasta n-i hacer Si A[j] > A[j+1] Entonces Intercambio (A[j],A[j+1])

Fin_si Fin _desde {bucle j} Fin_desde {bucle i}

void burbuja(int Lista[],int N){ int i, j,aux; for (j=1; j<N; j++) for (i=0; i < N-j;i++) if (Lista[i]> Lista[I+1]){ aux = Lista[I]; Lista[i] =Lista[i+1]; Lista[i+1]= aux; } } Burbuja mejorado El algoritmo burbuja se puede mejorar si disponemos de algn tipo de indicador que registre si se han producido intercambios en la pasada. Cuando se explor la lista y el indicador no refleje intercambios, la lista estar ya ocupada y se terminarn las comparaciones. El intercambio ser una variable lgica NoIntercambio (o bien ordenado) que se inicializa a 1 (significa que la lista a priori est desordenada). Si dos elementos se intercambian en una pasada. No Intercambio se pone en 0. Al principio de cada pasada NoIntercambio se fija a 1 y a 0 si se produce a intercambios. El bucle externo for se sustituye por un bucle do while o bien while y un contenido i se necesitara para contar el nmero de pasadas. i =1 Repetir NoIntercambio = true Desde j = i hasta n i hacer Si A[j] > A[J+1] Entonces Intercambio (A[j], A[j+1]) NoIntercambio = false Fin si Fin_desde i = i+1 Hasta que NoIntercambio = true void burbuja_mejorada(int Lista[],int N){ int i,j=1,aux,bandera=1; while (j<N && bandera==1){ Bandera=0; for(I=0;I<N-j;I++) if (Lista[I]>Lista[I+1]){ Bandera=1; Aux=Lista[I];

Lista[i]=Lista[i]; Lista[i+1]=aux; } j++; } Ordenacin por insercin Este mtodo est basado en la tcnica utilizada por los jugadores de cartas para clasificar sus cartas. El jugador va colocando (insertando) cada carta en su posicin correcta. Tres cartas Cuatro cartas Cinco cartas 2 2 2 6 6 6 10 //////// 9 //////// //////// 7 //////// 10 9 10

El mtodo se basa en considerar una parte de la lista ya ordenada y situar cada uno de los elementos restantes insertndolo en el lugar que le corresponde por su valor.

A[1] 1 A[N] 6

A[2] 4

A[3] 10

A[4] 15

A[5]

1 Algoritmo

10

15

{para cada elemento de la lista despus del primero} desde k = 2 hasta n hacer Guardar el valor de este elemento A[k] en una variable Aux. Hacer espacio para Aux desplazando todos los valores mayores que dicho valor A[k] una posicin. Insertar el valor de Aux en el lugar del ultimo valor desplazado. Fin_desde La operacin de desplazamiento se realiza con un procedimiento Desplazar, que mueve todos los elementos de la lista mayores que Aux, comenzando con el elemento de la

lista de posicin Aux-1. Si Aux es el valor ms pequeo hasta aqu, la operacin de desplazamiento termina despus que todos los elementos de la lista se han desplazado. Si Aux no es el valor ms pequeo, la operacin de desplazamiento termina cuando un valor menor o igual a Aux se alcanza. Aux se inserta en la posicin que ocupaba el ltimo valor que se desplaz.

Algoritmo de desplazamiento Mientras el primer elemento no se desplaza y el valor del elemento > Aux hacer o Desplazar elemento una posicin. o Comprobar valor del siguiente elemento. o Definir NuevaPos como posicin original del ltimo elemento desplazado. Fin_mientras Codificacin del procedimiento OrdenarInsercin

void OrdenacionInsercion(int Lista[];int n){ /*Lista (entrada/salida) , n (entrada) */ /*Lista = array de N elementos enteros */ int k, /*subindice del siguiente elemento al que se inserta*/ nueva_pos, /*subindice de este elemento despus de la insercin*/ aux; for(k=2;k<=n;k++){ aux = lista[k]; /*obtener siguiente elemento a insertar*/ Lista[nueva_pos(Lista,k,aux)]=aux; /*insertar aux en posicin nueva*/ } return 0; } La funcin de nueva posicin que desplaza todos los elementos de la lista int nueva_pos (int Lista[],int k,int aux ){ int encontrado ; {indicador} /*desplazar valores > Aux . Comenzar con el elemento K 1 */ encontrado= 0; while (k > 1 && !encontrado) if (Lista [k 1] > aux) { Lista[k] = Lista[k 1]; k--; } else encontrado = 1; return k; } {Desplazar}

Ordenacin por seleccin El algoritmo de ordenacin por seleccin de una lista (vector) de n elementos tiene los siguientes pasos: 1. Encontrar el elemento mayor de la lista. 2. Intercambiar el elemento mayor con el elemento de subndice n (o bien el elemento menor en el subndice 1). 3. A continuacin se busca el elemento mayor en la sublista de subndices 1...n 1, y se intercambiaba con el elemento de subndice n 1: por consiguiente, se sita el segundo elemento mayor en la posicin n-1. 4. A continuacin se busca el elemento mayor en la sublista 1...n 2 y as sucesivamente.

Lista desordenada

A[1] A[2] A[3] A[4] A[5]

5 14 -2 10 2

5 2 -2 10 14

5 2 -2 10 14

-2 2 5 10 14

El algoritmo de PosMayor debe guardar j como la posicin del elemento mayor y luego poder intercambiar.

int PosMayor (int Ultimo,int Lista[] ){ /*encuentra el indice del elemento mayor en la tabla [1.. Ultimo]*/ int Indice_Max, Indice; Indice_Max = 1; for(Indice= 2; Indice<=Ultimo;Indice++) if (Lista [Indice] > Lista [Indice_Max] ) indice_Max = Indice; return Indice_Max; }

void Seleccion (int Limi,int Lista[]){ int Aux, J, Mayor; for(J=Limi; >=2 ;J++) { /*encontrar el elemento mayor de 1..J*/ Mayor = PosMayor (J, Lista);

/*Intercambio con el elemento Tabla [J]*/ Aux = Lista[Mayor]; Lista[Mayor] = Lista[J]; Lista [J] = Aux; } }

Ordenamiento Shell La ordenacin Shell debe el nombre a su inventor, D. L. Shell. Se suele denominar tambin ordenacin por disminucin de incremento (gap). La idea general del mtodo (algoritmo) es la siguiente: Lista original 504 704 88 513 62 908 171 898 277 654 427 150 510 612 675 750

1. Se divide la lista original (16 elementos, en este ejemplo) en ocho grupos de dos (consideramos un incremento o intervalo de 16/2 = 8). 2. Se clasifica cada grupo por separado (se comparan las parejas de elementos y si no estan ordenados se intercambian entre si de posiciones). 3. Se divide ahora la lista en cuatro grupos de cuatro (intervalo o salto de 8/2 = 4) y nuevamente se clasifica cada grupo por separado. 4. Un tercer paso clasifica dos grupos de ocho registros y luego un cuarto paso completa el trabajo clasificando todos los 16 registros.

Primer paso (divisin/ordenacin por 8) 504 88 513 62 908 171 898 277 654 427 150 510 612 675 750

704

Segundo paso (divisin/ordenacin por 4) 504 88 150 62 612 171 760 277 654 427 513 510 908 675 898

704

Tercer paso (divisin/ordenacin por 2) 504 88 150 62 612 171 513 277 654 427 760 510 908 675 898

704

Cuarto paso (divisin/ordenacin por 1) 154 62 504 88 513 171 612 277 654 427 760 510 898 675 908 704

62

88

154 171 277

427 504 510 513 612 654 675 704

760 898 908

El algoritmo de Shell tiene diferentes modelos ms populares y citados en numerosas obras de programacin Algoritmo Intervalo = n div 2 Mientras (intervalo > 0 ) hacer Desde i = (intervalo + 1) hasta n hacer J = i intervalo Mientras (j >0 ) hacer K = j + intervalo Si ( a [j] <= a[k]) Entonces J=0 Si no Intercambio (a[j], a[k] Fin si j = j intervalo Fin mientras Fin desde Intervalo = intervalo div 2 Fin mientras

Cdigo void Intercambio (int X,int Y){ int Aux ;

Aux = X; X = Y; Y =Aux; } void Shell (int Lista[],int N){ int Intervalo =N/2, I, J, K ; while (Intervalo > 0){ for( I = Intervalo + 1; I <=N;I++) { J = I Intervalo; while (J > 0) { K = J + Intervalo; if (Lista[J] <= Lista[K]) J = 0; else Intercambio (*(Lista +J),*(Lista +K)); J = J Intervalo; } {while} } Intervalo /= 2; } return 0; }

Ordenamiento Mezcla (MergeSort) El proceso de mezcla, fusin o intercalacin (merge) consiste en tomar dos vectores ordenados (a, b) y obtener un nuevo vector tambin ordenado. El algoritmo ms sencillo para resolver el problema es: 1. Situar todos los elementos del vector a en el nuevo vector c. 2. Situar todos los elementos del vector b en el nuevo vector c. 3. Ordenar todo el vector c. Esta solucin no tiene en cuenta que los valores de de a y b ya estn ordenados. El algoritmo que tiene en cuenta la ordenacin es el siguiente: 1. Seleccionar el elemento de valor o clave mas pequeo con cualquiera de dos vectores y situarlo en el nuevo vector c. 2. Comparar a(i) y b(i) y poner el elemento de vector ms pequeo en c(k). 3. Seguir esta secuencia de comparaciones hasta que los elementos de un vector se hayan agotado en cuyo momento se copia el resto del otro vector en c.

Ejemplo: Mezclar las dos listas de nmeros a y b. 2 -15 4 0 78 13 97 15 lista A lista B

78

90

96

2 i

78

97

Lista A

j se ha incrementado junto con k

<
j Lista B Lista C

-15 0 -15 0 2 i < j

13

15

78

90

94

96

Lista C 4 78 97 Lista A

-15 0 -15

13

15

78

90

94

96

Lista B

B < A[j], de modo que C[k] se obtiene de B[j] Procedimiento mezcla de los vectores A y B void Mezcla (int A[],int B[],int C[],int M,int N ){ int I, J, K ; /*A Y B : entrada. Vectores ya ordenados*/ I=J=K=1; /*M Y N: nmero de elementos de A y B respectivamente*/
Comparar A[i] Y B[j]. Poner el Ms pequeo en C[k]. Incrementar Los indices apropiados

while ((I <= M) &&(J <= N)) { /*C : salida. Vector mezcla ordenado*/ if (A[I] <= B[J]){ /*El tipo Lista, tendr una longitud minima de M + N elementos*/ C [K] = A[I]; I++; } else { C [K] = B[J]; J ++; } K++; } {copiar el resto del vector no agotado} if (I > M) for( P=J;P<=N;P++){ C [K] = B [P]; K++; } else for( P=I;P< M;P++){ C [K] = A [P]; K++; } return 0; }

Bsquedas Bsqueda secuencial Un problema importante en el proceso de datos, como ya se ha comentado, es la bsqueda en un conjunto de datos de un elemento especifico y la recuperacin de alguna informacin asociada al mismo. La bsqueda lineal o secuencial es la tcnica ms simple para buscar un elemento en un arreglo (vector). Consiste el mtodo en el recorrido de todo el vector, desde el primer elemento hasta el ltimo, y de uno en uno. Si el vector contiene el elemento, el proceso devolver la posicin del elemento buscado y en caso contrario un mensaje que indique la falta de xito en la bsqueda. Supongamos una lista de nmeros de la seguridad Social incluidos en un arreglo a y se desea buscar a ver si existe el nmero 453714.

A[1} A [2] A [3] A[4] -

120467 401321 25761 Elemento a buscar: t 453714

451871 Nmeros Seguridad Social Mediante un bucle desde ir comparando el elemento t buscando con a[i], donde i vara, A[98] 339412 A[99] 81467 A[100] 924116 en el ejemplo anterior, de 1 a 100. En caso de encontrarlo, almacenar la posicin (el indice arreglo) del mismo dentro de la lista y finalmente se devolver al programa principal. Pseudocdigo 1 Posicin = 0 {lista = vector a[i] de n elementos} desde i = 1 hasta n hacer si a[i] = t entonces Posicin = i fin si fin desde Este algoritmo tiene un inconveniente, sea cual sea el resultado se recorre el vector completo. El algoritmo se puede mejorar con un bucle while o do_while, y utilizando unas banderas que detecten cuando se encuentre el elemento. El bucle se terminar por dos causas: La bandera o indicador toma el valor esperado y la bsqueda ha tenido xito. El valor del ndice i es mayor que el nmero de trminos de la lista, lo que significa que se ha terminado de recorrer la misma y el elemento buscado no ha aparecido.

Pseudocdigo 2 Encontrado = falso Posicin = 0 i=1 mientras (i <= n) y (No Encontrado=verdadero) hacer si a[i] = t entonces Posicin = i Encontrado = verdadero Fin si i=i+1 fin_mientras

Funcin bsqueda lineal int BusquedaLineal (int A[]; /*entrada, vector bsqueda*/ int N ; /* entrada, nmero de elementos */ int T /*elemento a buscar*/){ int Encontrado=0,I=1,Posicion; Posicion= 0; /*posicin del elemento caso de no xitir*/ while (I <= N) && ! Encontrado){ if (A[I] == T ){ Posicion= I; Encontrado = 1; } {fin del if y del while} I ++; return 0; } {posicin del elemento en la lista Bsqueda Binaria La bsqueda lineal, por sus simplicidad es buena para listas de datos pequeas para listas grandes es ineficiente, la bsqueda binaria es el mtodo idneo. Se basa en el conocido mtodo divide y vencers. Este mtodo tiene una clara expresin en la bsqueda de una palabra en un diccionario. Cuando se busca una palabra no se comienza la bsqueda por la pgina 1 y se sigue secuencialmente sino que se abre el diccionario por una pagina donde aproximadamente se piensa puede estar la palabra, es decir se divide el diccionario en dos partes, al abrir la pgina se ve si se ha acertado o en que parte se encuentra la palabra buscada. Se repite este proceso hasta que por divisiones o aproximaciones sucesivas se encuentra la palabra. Supongamos que la lista donde se busca es 1331 1373 1555 1850 1892 1898 1989 2002 2400 2670 3200

Elemento central

Elemento buscado

Y que se busca el nmero 1989 Se examina en primer lugar el elemento central de la lista (las divisiones se toman iguales) 1898. Dado que 1989 es mayor que 1898, el elemento a buscar estar en la segunda mitad. Por consiguiente, se sigue la bsqueda en esta mitad: Elemento a buscar 1989 2002 2400 2670 3200

Elemento central

El elemento central en esta sublista es 2400, y como1989 es menor, la nueva sublista donde buscar es

1989 2002

Elemento considerado central

como ya no hay elemento central se toma el nmero inmediatamente anterior de la posicin central, que en este caso es 1989. En este caso se ha encontrado el elemento deseado en tres comparaciones, mientras que en la bsqueda lineal hubiese necesitado al menos seis comparaciones. Este mtodo es muy eficiente con el nico inconveniente, que requiere la lista ordenada. Algoritmo 1. Establecer Primero = 1 y Ultimo = n (n, nmero de elementos). Estas variables representan la primera y ltima posicin de la lista o sublista donde se est buscando y permite el calculo de la posicin del elemento central. 2. Encontrado = falso . 3. mientras Primero <= Ultimo y Encontrado = falso hacer {Encontrar posicin central} Central = (Primero + Ultimo) div 2 {Comparar elemento buscado t con A[Central]} si t = a [Central] entonces Encontrado = verdadero sino si t > A [Central] entonces Primero = Central + 1 sino Ultimo = Central 1 fin mientras 4. si Encontrado = verdadero entonces Posicin = Central {existe elemento} si no Posicin = 0 {no se ha encontrado} fin_si La bsqueda binaria requiere una ordenacin previa del vector o lista en el que se va ha efectuar la bsqueda. Por consiguiente, las acciones tpicas (mdulos) en un algoritmo de bsqueda binaria son: 1. 2. 3. 4. Lectura del vector Ordenacin del vector Bsqueda binaria Visualizar resultado

int Binaria (int T, int L[] ,int N ){ int Primero, Ultimo, Central, Encontrado; Primero = 1; Ultimo = N; Encontrado = 0 ; while ((Primero <= Ultimo) && !Encontrado){ Central = ( Primero + Ultimo) / 2;

if (T == L [Central]) Encontrado = 1; else if ( T > L [Central]) Primero = Central + 1; else Ultimo = Central 1; } if (!Encontrado) return 0; else return Central; }