29
TEMA 2 CLASIFICACIÓN EN MEMORIA PRINCIPAL Métodos directos INSERCIÓN DIRECTA Se basa en coger el primer elemento de la parte desordenada y buscar la posición que le corresponda dentro de la parte ordenada. Paso1: Partimos de un Array aleatoriamente ordenado y marcamos su primer elemento como parte ordenada. El resto será la parte desordenada. Paso2: Cogemos el primer elemento de la parte no ordenada y lo almacenamos en una variable centinela (a[0]) Paso3: Comparamos empezando por el final de la parte ordenada hasta que encontramos un elemento menor. Paso4: Movemos una posición a la derecha todos los elementos que han resultado mayores que el que queremos insertar e instalamos el centinela en la posición encontrada. 1 2 3 4 5 6 7 Llaves iniciales 8 14 5 9 3 23 17 = i=2 8 14 5 9 3 23 17 i=3 5 8 14 9 3 23 17 = = i=4 5 8 9 14 3 23 17 i=5 3 5 8 9 14 23 17 = i=6 3 5 8 9 14 23 17 i=7 3 5 8 9 14 17 23 Análisis El número de comparaciones C en la i-ésima extracción es a lo sumo i-1 y como máximo 1; Suponiendo que todas las permutaciones de n llaves sean igualmente probables (i/2 en promedio). El número M de movimientos (asignación de elementos) es C i +2 (incluido el centinela). Por tanto, los números totales de comparaciones y movimientos son: Comparaciones Movimientos Mínimo Llaves del arreglo inicial, ordenadas Máximo Llaves del arreglo inicial, completamente desordenadas 1

TEMA 2. Clasificación en memoria principal

Embed Size (px)

DESCRIPTION

Estructuras de datos y algoritmos.TEMA 2. Clasificación en memoria principal

Citation preview

Page 1: TEMA 2. Clasificación en memoria principal

TEMA 2 CLASIFICACIÓN EN MEMORIA PRINCIPALMétodos directos

INSERCIÓN DIRECTASe basa en coger el primer elemento de la parte desordenada y buscar la posición

que le corresponda dentro de la parte ordenada.Paso1: Partimos de un Array aleatoriamente ordenado y marcamos su primer

elemento como parte ordenada. El resto será la parte desordenada.Paso2: Cogemos el primer elemento de la parte no ordenada y lo almacenamos en

una variable centinela (a[0])Paso3: Comparamos empezando por el final de la parte ordenada hasta que

encontramos un elemento menor.Paso4: Movemos una posición a la derecha todos los elementos que han resultado mayores que

el que queremos insertar e instalamos el centinela en la posición encontrada.1 2 3 4 5 6 7

Llaves iniciales 8 14 5 9 3 23 17=

i=2 8 14 5 9 3 23 17

i=3 5 8 14 9 3 23 17= =

i=4 5 8 9 14 3 23 17

i=5 3 5 8 9 14 23 17=

i=6 3 5 8 9 14 23 17

i=7 3 5 8 9 14 17 23

AnálisisEl número de comparaciones C en la i-ésima extracción es a lo sumo i-1 y como

máximo 1; Suponiendo que todas las permutaciones de n llaves sean igualmente probables (i/2 en promedio).

El número M de movimientos (asignación de elementos) es C i+2 (incluido el centinela). Por tanto, los números totales de comparaciones y movimientos son:

Comparaciones MovimientosMínimoLlaves del arreglo inicial, ordenadasMáximoLlaves del arreglo inicial, completamente desordenadasPromedioLlaves del arreglo inicial,aleatoriamente ordenadas

1

Page 2: TEMA 2. Clasificación en memoria principal

El algoritmo completo es:MODULE InsercionDirecta;

FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR i,j: INTEGER; n: INTEGER;VAR a: tipoarray;

BEGIN(* carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-i; END;

(* Algoritmo de clasificación *)FOR i:=2 TO n DO

a[0]:=a[i]; (* Garantiza la salida del while *)j:=i;WHILE a[0]<a[j-1] DO

a[j]:=a[j-1]; (* movimientos *)j:=j1

END;a[j]:=a[0] (* inserción *)

END;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END InsercionDirecta.

2

Page 3: TEMA 2. Clasificación en memoria principal

INSERCIÓN BINARIAEste algoritmo se basa en el de inserción directa. Es un método de inserción que

difiere de la inserción directa simplemente en la búsqueda de la posición donde insertaremos.

Paso 1: Hallamos el elemento central del área comprendida por la parte ordenada más la posición del elemento a insertar.

Paso2: Comparamos el elemento central con el elemento que queremos insertar. Si dicho elemento central es menor o igual nos quedamos con la parte superior (SIN INCLUIR EL ELEMENTO CENTRAL). En caso contrario nos quedamos con la mitad inferior, INCLUYENDO el elemento central.

Paso3: Repetimos el mismo proceso sobre el área con la que nos hemos quedado hasta que dicha área sea nula.

Paso4: Cuando el área sea nula tendremos la posición de inserción.3 5 8 9 1

314

17

20

22

23

25

30

32

40

46

50

15

60

7 1

*

3 5 8 9 13

14

17

20

22

23

25

30

32

40

46

50

15

60

7 1

*

3 5 8 9 13

14

17

20

22

23

25

30

32

40

46

50

15

60

7 1

*

3 5 8 9 13

14

17

20

22

23

25

30

32

40

46

50

15

60

7 1

*

3 5 8 9 13

14

17

20

22

23

25

30

32

40

46

50

15

60

7 1

*

3 5 8 9 13

14

15

17

20

22

23

25

30

32

40

46

50

60

7 1

AnálisisEl número de movimientos no mejora significativamente con respecto al método

de inserción directa y seguirán siendo de orden n2 La posición de inserción se encuentra cuando L=R. En consecuencia, el intervalo

de búsqueda debe ser, al final, de longitud 1; lo que supone dividir a la mitad el intervalo de longitud N=log n veces, donde n es el número de veces que se divide por 2. La

inserción se producirá cuando , aproximado por la integral

quedando después de operar como El número de comparaciones es esencialmente independiente del orden

inicial de los elementos. Sin embargo dado el valor truncador de la división el número de comparaciones puede ser hasta uno más de lo previsto. Esto es debido a que las posiciones de inserción en el extremo inferior se localizan en promedio más pronto que las del extremo superior, con lo que se favorecen los casos en que los elementos están fuera de orden al principio. El número menor corresponde a cuando es orden es inverso y el máximo cuando ya están en orden.

La mejora sobre la inserción directa es sólo en el número de comparaciones, no al de movimientos requeridos.

Como mover elementos es más lento que compararlos, la mejora no es radical.

3

Page 4: TEMA 2. Clasificación en memoria principal

El algoritmo completo es:MODULE InsercionBinaria;

FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR i,j,m,L,R: INTEGER; n: INTEGER; x: INTEGER;VAR a: tipoarray;

BEGIN(* carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-1i; END;

(* Algoritmo de clasificación *)FOR i:=2 TO n DO

x:=a[i];(* L: índice al elemento de la parte izquierda del

subarray en el que se realiza la búsqueda en cada paso *)L:=1;(* R: índice al elemento de la parte derecha del

subarray en el que se realiza la búsqueda en cada paso *)R:=i;WHILE L<R DO

m:=(L+R)DIV 2;IF a[m]<=x THEN

L:=m+1;ELSE

R:=m;END

END;FOR j:=i TO R+1 BY 1 DO

a[j]:=a[j1]; (* desplazamiento *)END;a[R]:=x; (* inserción *)

END;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END InsercionBinaria.

4

Page 5: TEMA 2. Clasificación en memoria principal

SELECCIÓN DIRECTASe trata de elegir el menor elemento de entre todos los de la parte no ordenada.

Este elemento se intercambiara por el primero de dicha parte.Paso1: Partimos de un Array en el que todo será parte no ordenada.Paso2: Cogemos el primer elemento de la parte no ordenada y lo guardamos en

una variable llamada menor. También almacenaremos su posición en posMenor.Paso3: Recorremos toda la parte no ordenada comparando el menor con cada

elemento. Si encontramos uno menor almacenaremos dicho elemento y su posición.Paso4: Intercambiamos el elemento almacenado como menor con el 1º de la parte no ordenada y

repetimos desde el paso 2 con la parte no ordenada una posición más a la derecha.1 2 3 4 5 6 7

Llaves iniciales 8 14 5 9 3 23 17

i=2 3 14 5 9 8 23 17

i=3 3 5 14 9 8 23 17

i=4 3 5 8 9 14 23 17=

i=5 3 5 8 9 14 23 17=

i=6 3 5 8 9 14 23 17

i=7 3 5 8 9 14 17 23

AnálisisComparacionesEl número de comparaciones es independiente del orden inicial de llaves n−1,

n−2,..., 1, sumando todas ellas se observa que es una suma aritmética y por tanto el número de comparaciones será de orden n2 Así se tiene:

Movimientosa) Mejor caso:Las llaves iniciales están ordenadas

b) Peor caso:Las llaves iniciales están completamente desordenadas (en orden inverso)

5

Page 6: TEMA 2. Clasificación en memoria principal

c) Caso promedio:En el caso promedio, las llaves iniciales están ordenadas aleatoriamente y habrá

que utilizar argumentos probabilísticos. Dado que el procedimiento rastrea el arreglo, comparando cada elemento con el valor mínimo descubierto hasta el momento y, si es más pequeño hace una asignación. La probabilidad de que el segundo elemento sea menor que el primero es 1∕2, la del tercero 1/3, la del cuarto 1∕4, así sucesivamente, con lo que el número total esperado de movimiento es Hn1, donde Hn es el enésimo número armónico Hn= 1 + 1∕2 + 1/3 +... + 1/n Que se puede expresar como Hn= ln n + g + 1∕2 n 1/ 12n2+... donde g es la constante de Euler. Con una n suficientemente grande se puede aproximar el número promedio de asignaciones como: Fi= ln i + g + 1

El número promedio de movimientos en la clasificación por selección, es pues,

, aproximando la integral se obtiene el valor aproximado

Este resultado permite concluir que el método de selección directa es preferible al de inserción directa ya que su número de movimientos promedio es de orden ln n Pero si se compara con la inserción binaria cabe preguntarse cuál es más adecuado ya que éste tiene un coste de n2 para los movimientos pero de orden log n para las comparaciones, mientras que en la selección directa es de orden n2 para las comparaciones y de ln n para los movimientos. La decisión en esta situación viene determinada por consideraciones de bajo nivel. En general, la implementación de una comparación tiene un coste inferior al del movimiento. Por tanto, la selección directa será la opción a elegir en general, aunque la inserción es algo más rápida cuando las llaves se clasifican predominantemente al principio.

6

Page 7: TEMA 2. Clasificación en memoria principal

El algoritmo completo es:MODULE SeleccionDirecta;

FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR i,j,k: INTEGER; n,x: INTEGER;VAR a: tipoarray;

BEGIN(* carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-i; END;

(* Algoritmo de clasificación *)FOR i:=1 TO n-1 DO

k:=i;x:=a[i]; (* Seleccion inicial *)FOR j:=i+1 TO n DO (* busqueda en secuencia fuente *)

IF a[j]<x THENk:=j;x:=a[k]; (* seleccion *)

END;END;a[k]:=a[i]; (* intercambio *)a[i]:=x;

END;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END SeleccionDirecta.

7

Page 8: TEMA 2. Clasificación en memoria principal

INTERCAMBIO DIRECTO (BURBUJA)Este algoritmo consistirá en recorrer el array comparando los elementos que están

en posiciones contiguas. Si estos están desordenados se intercambian. Paso1: Partimos de un array inicialmente desordenado en el que la parte

desordenada ocupara su totalidad.Paso2: Empezando SIEMPRE desde la primera posición del Array vamos subiendo

hacia posiciones posteriores comparando los elementos consecutivos dos a dos.Paso 3: Si dichos elementos están desordenados se intercambian consiguiendo que

al final de un recorrido nos quede el elemento de mayor valor del parte desordenada en la ultima posición.

Paso4: Incrementamos la parte ordenada una posición a la izquierda desde el final y repetimos el mismo proceso desde el paso 2 hasta que la parte ordenada alcance la primera posición.

1ª pasada

j=1 j=2 j=3 j=4

8 8 8 8 814 1

45 5 5

5 5 14

9 9

9 9 9 14

14

3 17

17

17

17

4 iteraciones

2ª pasa

da

j=1 j=2 j=3

8 5 5 55 8 8 89 9 9 9

14 14

14

14

17 17

17

17

3 iteraciones

3ª pasa

da

j=1 j=2

5 5 58 8 89 9 9

14 14

14

17 17

17

2 iteraciones

4ª pasa

da

j=1

5 58 89 9

14 14

17 17

1 iteración

8

Page 9: TEMA 2. Clasificación en memoria principal

AnálisisLas operaciones más frecuentes características del algoritmo son la comparación

de elementos del arreglo y los movimientos entre elementos del arreglo. También como en la selección directa, el número de comparaciones es independiente del orden inicial de las llaves del arreglo ya que siempre se recorre por completo la parte desordenada del arreglo para comparar las parejas de llaves adyacentes.

ComparacionesEl número de comparaciones es independiente del orden inicial de llaves n−1,

n−2, ..., 1 sumando todas ellas se observa que es una suma aritmética y por tanto el número de comparaciones será de orden n2 Así se tiene:

Movimientosa) Mejor caso:Las llaves iniciales están ordenadas

Nunca se entra en el IF, por tanto el intercambio formado por tres movimientos, no se realiza nunca

b) Peor caso:Las llaves iniciales están completamente desordenadas (en orden inverso)

En este caso se realiza siempre la comparación.c) Caso promedioEn el caso promedio, las llaves iniciales están ordenadas aleatoriamente y habrá

que utilizar argumentos probabilísticos. El intercambio se realizará dependiendo de que un número entero sea mayor o menor que otro, hecho de probabilidad 1/2 suponiendo equiprobables los enteros. Así el número promedio de movimientos es:

O lo que es lo mismo:

9

Page 10: TEMA 2. Clasificación en memoria principal

El algoritmo completo es:MODULE IntercambioDirecto;

FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR i,j: INTEGER; n,aux: INTEGER;VAR a: tipoarray;

BEGIN(* carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-i; END;

(* Algoritmo de clasificación *)FOR i:=1 TO n-1 DO

FOR j:=1 TO n-i DOIF a[j]>a[j+1] THEN (* comparar elementos contiguos *)

aux:=a[j+1]; (* intercambiar *)a[j+1]:=a[j];a[j]:=aux;

END;END;

END;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END IntercambioDirecto.

10

Page 11: TEMA 2. Clasificación en memoria principal

SACUDIDA O VIBRACIÓNEs un método de clasificación por intercambio que mejora el método de la

clasificación por burbuja (intercambio directo) alternando la dirección de pases consecutivos. Los pases impares se harán en sentido descendente, mientras que los pares lo harán en sentido ascendente. En cada pasada, la parte del arreglo a ordenar estará marcada por los índices L y R que indicarán respectivamente el inicio y el final de dicha parte. En cada pasada hacia el final se decrementará (R), ya que el último elemento se coloca en su sitio y en cada pasada hacia el inicio se incrementará el índice de inicio (L) por la razón, simétrica de la anterior, de que el menor de los elementos ha alcanzado su posición definitiva. El algoritmo se detiene cuando estos índices se cruzan.

Se basa en el mimo concepto de intercambio que el algoritmo de la burbuja salvo que alterna el sentido del recorrido.

Paso1: Partimos de un array inicialmente desordenado en el que la parte desordenada ocupara su totalidad.

Paso2: Recorremos el array en sentido ascendente desde la primera (L) hasta la ultima posición de la parte desordenada (R) comparando elementos consecutivos e intercambiándolos cuando sea necesario. NOTA: En este algoritmo empezamos a recorrer desde L que no será siempre la 1ª Posición del Array.

Paso 3: Una vez acabado el recorrido debemos marcar la ultima posición donde hubo intercambio para que en la pasada del sentido contrario dicha pasada nos sirva de punto de partida

Paso 4: Repetimos el mismo proceso en sentido contrario hasta que lleguemos a la posición L marcando donde se realizó el ultimo intercambio.

Paso 5: Repetimos el mismo proceso desde 2 una vez actualizada la L Hasta que L sea mayor que R.

1ª pasada

L=1

+1  

R=n-1=5

j=1 j=2 j=3 j=4

8 8 8 8 814 1

45 5 5

5 5 14

9 9

9 9 9 14

14

3 17

17

17

17

k=4

2ª pasada

L=1

-1  

R=k=4

j=1 j=2 j=3

8 5 5 55 8 8 89 9 9 9

14 14

14

14

17 17

17

17

k=1

3ª pasada

L=k+1=2

+1  

R=k-2=3

j=1 j=2

5 5 58 8 89 9 9

14 14

14

17 17

17

k=2

11

Page 12: TEMA 2. Clasificación en memoria principal

4ª pasada L=2

+1  

R=k-1=1

j=1

5 58 89 9

14 14

17 17

R<L (1<2)

Ordenación completa

AnálisisLa primera observación importante es que las mejoras realizadas sobre la

clasificación por burbuja (intercambio directo) no reducen el número de movimientos a realizar ya que los intercambios para colocar en su lugar una llave serán los mismos. La mejora se realiza únicamente en el número de comparaciones, eliminando las que se ejecutan de forma redundante.

ComparacionesEl número mínimo de comparaciones será:

El número máximo de comparaciones será:

El número promedio de comparaciones será:

Siendo k1 y k2 constantes de proporcionalidad. Teniendo en cuenta que la implementación de los movimientos tiene un coste mayor que el de las comparaciones puede decirse que la mejora no es significativa.

12

Page 13: TEMA 2. Clasificación en memoria principal

El algoritmo completo es:MODULE SacudidaVibracion;

FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR j,k,L,R: INTEGER; n,aux,i: INTEGER;VAR a: tipoarray;

BEGIN(* carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-i; END;

(* Algoritmo de clasificación *)L:=1; R:=n1;k:=1;REPEAT

FOR j:=L TO R DO (* pase de bajada *)IF a[j]>a[j+1] THEN (* comparar elementos contiguos *)

aux:=a[j+1]; (* intercambiar *)a[j+1]:=a[j];a[j]:=aux;k:=j;

END;END;R:=k-1;FOR j:=R TO L BY 1 DO (* pase de subida *)

IF a[j]>a[j+1] THEN (* comparar elementos contiguos *)aux:=a[j+1]; (* intercambiar *)a[j+1]:=a[j];a[j]:=aux;k:=j;

END;END;L:=k+1;

UNTIL L>R;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END SacudidaVibracion.

13

Page 14: TEMA 2. Clasificación en memoria principal

COMPARACIÓN DE LOS MÉTODOS DIRECTOS DE CLASIFICACIÓNDe los análisis de los costes computacionales de realizados para cada algoritmo,

puede establecerse que el coste computacional de los algoritmos de clasificación directa es de orden n2

De todos los métodos, el de selección directa, será el más recomendable, a elegir cuando el array está aleatoriamente ordenado.

El método de inserción binaria, será el más rápido, cuando el desorden se encuentre en las primeras posiciones del array

El método de vibración, será el más eficiente, cuando el array está inicialmente ordenado.

14

Page 15: TEMA 2. Clasificación en memoria principal

METODOS AVANZADOS

INSERCIÓN POR INCREMENTO DECRECIENTE (SHELL)Se trata de ir realizando la inserción directa con todos los elementos que difieren

en hi posiciones dentro del array. Posteriormente haremos la inserción directa con elementos que difieran hi posiciones y así sucesivamente hasta obtener la ordenación total.

NOTA: Para que este algoritmo realice una clasificación satisfactoria el último número de elementos del conjunto de incrementos decrecientes debe ser igual a 1, caso en el que se realizará la inserción directa normal.

Paso 1: Cogemos el primer elemento del conjunto de incrementos decrecientes y vamos haciendo grupos con los elementos que difieren en tantas posiciones como nos indique dicho número [4, 2, 1].

NOTA: Siempre nos quedaran tantos grupos como el elemento hi

6 1 8 7 2 4 3 10 0 22Grp1 Grp2 Grp3 Grp4 Grp1 Grp2 Grp3 Grp4 Grp1 Grp2

Paso 2: Realizamos la inserción directa con cada uno de los grupos. Para la implementación lo que haremos pasar el elemento que queremos insertar al centinela y compararlo con el último de la parte ordenada hi posiciones anteriores. El momento en el que encontremos un elemento menor o el principio del array pararemos y movemos todos los elementos del mismo grupo hi posiciones hacia la derecha.

0 1 3 7 2 4 8 10 6 22Grp1 Grp2 Grp3 Grp4 Grp1 Grp2 Grp3 Grp4 Grp1 Grp2

Paso 3: Una vez hecha la inserción directa sobre los hi grupos, cogemos el siguiente elemento del conjunto de incrementos decrecientes h2 y volvemos al paso 1 hasta que no queden elementos por coger.

0 1 3 7 2 4 8 10 6 22Grp1 Grp2 Grp1 Grp2 Grp1 Grp2 Grp1 Grp2 Grp1 Grp2

Ventaja de este Método: Con respecto a la inserción directa este método este método mejora el número de movimientos ya que antes de llegar al incremento decreciente 1 los elementos del array se han ido posicionando cerca del lugar que ocuparan al final con desplazamientos “a gran escala”.

NOTA: Cuando el conjunto de incrementos decrecientes esta compuesto por elementos que son múltiplos entre si la clasificación no será tan efectiva porque ya habremos incluido en el mismo grupo a varios elementos que ya se compararon en iteraciones anteriores. Existen dos formas “mejores” de elegir los elementos:

Hibbard se escogen (2n)-1: por ejemplo 15, 7, 3, 1. En este caso, en el caso, peor el coste es de n1.3 y en el promedio n1.2

Sedgewick propuso otras secuencias, en las cuales, el coste en el peor caso es n(4/3) y en el promedio n(7/6)

En ambos casos el caso promedio no está demostrado analíticamente.

15

Page 16: TEMA 2. Clasificación en memoria principal

AnálisisEl análisis detallado de este algoritmo requiere una elaboración matemática

rigurosa en función de los posibles incrementos decrecientes. No se sabe que elección de incrementos produce mejores resultados, pero se ha podido establecer que no deben ser múltiplos de sí mismos.

El peor caso es de especial interés. Se da cuando en un arreglo de n posiciones en las posiciones pares se encuentran llaves con números grandes, mientras que en las posiciones impares se encuentran claves con números pequeños. Los incrementos se toman pares excepto el último (h1=1). El análisis matemático demuestra que el peor coste es de n1.3, con lo que mejora los métodos directos.El algoritmo de clasificación es:MODULE IncrementoDecreciente;

FROM InOut IMPORT WriteInt, WriteLn, WriteString;TYPE tipoarray=ARRAY[0..9] OF INTEGER;VAR a: tipoarray;CONST t=3; (* numero de ordenaciones por inserción directa *)VAR i,j,k,n,s: INTEGER; (* posición del centinela de cada clasificación *)m:[1..t]; (* índice que indica el numero de ordenación *)h:ARRAY[1..t] OF INTEGER; (* vector de incrementos *)

BEGIN(* carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-I; END;

(* Algoritmo de clasificación *)h[1]:=4; h[2]:=2; h[3]:=1;FOR m:=1 TO t DO

k:=h[m]; s:=-k;FOR i:= k+1 TO n DO

j:=i-k;IF s=0 THEN s:=-k END;s:=s+1; a[s]:=a[i]; (* Inserción directa *)WHILE a[s]<a[j] DO

a[j+k]:= a[j]; j:=j-kEND;a[j+k]:=a[s]

END;END;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END IncrementoDecreciente.

16

Page 17: TEMA 2. Clasificación en memoria principal

CLASIFICACIÓN POR MONTÓNTambién se conoce como Heap Sort. Williams define un montón según la secuencia

de llaves hi, i=L, L+1,..., R, tal que mantienen la siguiente relación de orden: h i ≤ h2i y hi

≤ h2i+1 para i = L,..., R/2. Floyd considera que en un arreglo h1,..., hn; los elementos de la segunda mitad del arreglo forman un montón por si mismos, ya que en los elementos hm,..., hn con m= (n DIV 2) + 1, no hay dos índices i, j tales que j = 2 * i. A estos elementos se les puede considerar como el montón de la parte inferior del árbol, entre los que no se requiere ninguna relación de ordenación. El montón debe ampliarse hacia la izquierda, con lo que en cada paso se incluye un nuevo elemento y se coloca correctamente con un desplazamiento.

Construcción de un montón44 55 12 42 | 94 18 06 6744 55 12 | 67 94 18 06 4244 55 | 18 67 94 12 06 4244 | 94 18 67 55 12 06 42| 94 67 18 44 55 12 06 42

Cada vez que se añade un elemento al montón hay que comprobar que cumple la definición de Williams y si no, hay que intercambiarlo.

Clasificación94 67 18 44 | 55 12 06 4267 55 18 44 | 42 12 06 9455 44 18 | 06 42 12 67 9444 42 18 | 06 12 55 67 9442 12 18 | 06 44 55 67 9418 12 | 06 42 44 55 67 9412 06 | 18 42 44 55 67 9412 | 06 18 42 44 55 67 9406 | 12 18 42 44 55 67 94

AnálisisEl peor caso se produce cuando se realiza el máximo número de intercambios en

la construcción de los sucesivos montones. En cada pase i, la reconstrucción de un montón requerirá 2log i comparaciones. Como se hizo en la inserción binaria, el número de comparaciones en el peor caso es 2n log n − On .

El caso promedio resulta ser del orden de 2n log n − O n log log n .

17

Page 18: TEMA 2. Clasificación en memoria principal

El algoritmo completo es:

MODULE ClasificacionMonton;FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR i,j,m,k,L,R: INTEGER; n: INTEGER; x: INTEGER;VAR a: tipoarray;

(* Procedimiento auxiliar *)PROCEDURE amontonar(L,R:INTEGER);

(* R:posicion del extremo derecho del monton *)(* L:posicion del elemento que se esta incorporando al monton *)VAR i,j:INTEGER; x:INTEGER;

BEGINi:=L; j:=2*L; x:=a[L]; (* elemento que se incorpora al monton *)IF (j<R) AND (a[j+1]<a[j]) THEN j:=j+1 END;(*j: ¡ndice del elemento que intercambiar de entre el 2i y el 2i+1 *)WHILE (j<=R) AND (a[j]<x) DO

a[i]:= a[j]; a[j]:=x; (* intercambio *)i:=j;IF(j<R) & (a[j+1]<a[j]) THEN j:=j+1 END (* verificar monton hasta el final *)

END;END amontonar;(* Fin Procedimiento auxiliar *)

18

Page 19: TEMA 2. Clasificación en memoria principal

BEGIN(* Carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10i END;

(* Algoritmo de clasificación *)L:=(n DIV 2)+1;R:=n;WHILE L>1 DO (* crear el montón *)

L:=L1;(* posición del nuevo elemento que se incorpora al montón *)amontonar(L,R);

END;WHILE R>1 DO (* clasificar según montón *)

x:= a[1];a[1]:=a[R];a[R]:=x;R:=R1;amontonar(L,R);

END;(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END ClasificacionMonton.

19

Page 20: TEMA 2. Clasificación en memoria principal

CLASIFICACIÓN POR PARTICIÓN (QUICK SORT)Este método desarrollado por C.A.R. Hoare. Es el mejor algoritmo de ordenación.

Está basado en el método de intercambio (burbuja) que, era el peor de los métodos directos. Al igual que todos los métodos avanzados, cuanto mayor sea la distancia entre los elementos que se intercambian más eficaz será la clasificación.

Se elige un valor de pivote al azar, x. Recorreremos el arreglo desde la izquierda hasta encontrar una llave mayor que el pivote, i, y desde la derecha hasta encontrar una menor, cuando esto suceda intercambiaremos ambos elementos y avanzaremos los índices, siguiendo así hasta que se crucen. El objetivo es poner a la derecha todos los mayores o iguales que el pivote y a la izquierda todos lo menores. Veamos un ejemplo.

x46 57 14 44 96 20 8 70i j

Elegimos como pivote el de en medio (por ejemplo, podríamos haber elegido otro cualquiera). Avanzaremos la i hasta que encontremos algún elemento mayor que el 44 y retrocederemos la j hasta que encontremos alguno menor.

a[i]=57>44; se paraj=j-1;a[j]=20<44; se paraIntercambiamos ambos elementos. Avanzamos i y retrocedemos j

8 57 14 44 96 20 46 70i j

a[i]=57>44; se paraa[j]=20<44; se paraIntercambiamos ambos elementos. Avanzamos i y retrocedemos j

8 20 14 44 96 57 46 70i j

Avanzamos i y descendemos j8 20 14 44 96 57 46 70

ijComo a[i] y a[j] son iguales que el pivote intercambiamos y avanzamos (el objetivo de este

intercambio es simplemente el avanzar y que así se crucen).8 20 14 44 96 57 46 70

j iUna vez se han cruzado los índices pararíamos y tendríamos dos subvectores el de

la derecha con los elementos mayores que el pivote y el de la izquierda con los menores, estando el pivote por tanto en su posición.

A continuación haríamos llamadas recursivas a cada subvector hasta que sean de tamaño 1 momento en el cual tendríamos ordenado el arreglo inicial.

20

Page 21: TEMA 2. Clasificación en memoria principal

AnálisisEste método es de naturaleza recursiva por lo que su análisis hará uso de formulas

de recurrencia. Para el análisis se supone un pivote de valor aleatorio. El coste vendrá dado por dos llamadas recursivas más el tiempo que transcurre en la partición. Así la formula de clasificación por partición será:

T n = Ti + T n−i−1 + cn T1 = T0 = 1Donde i es el número de elementos en la partición de los menores.En el peor caso el pivote es un extremo (el mayor o el menor elemento de todas

las particiones) y su coste será:T n = Tn−1 + cn, n1

Aplicando esta ecuación se llega a T n=T1+c = On2 por lo tanto, en el peor

de los casos el coste es n2

En el mejor de los casos el pivote queda en el centro, quedando la formula:

T n=2T + cn sustituyendo en las ecuaciones se llega a: T n=cn log n+n =On log n

En conclusión, en el mejor caso la clasificación por partición tiene un coste de orden

n log nEn el caso promedio se supone que todos los tamaños de la partición con

elementos menores que el pivote son igualmente probables. Por tanto su probabilidad es 1/n. Después de realizar todas las operaciones de sustitución y transformación, haciendo uso de los números armónicos, la suma final queda como: lnn1−32

Siendo la constante de Euler, el caso promedio queda como T n =O n log n

Cálculo del k-ésimo mayor elementoEl algoritmo de clasificación por partición permite, además de clasificar un arreglo,

calcular de forma eficaz el k-ésimo elemento mayor del mismo. Toda vez que para calcular la mediana se debe calcular el k-ésimo elemento mayor, con k = n/2 , por generalidad se resolverá el problema para k.

El k-ésimo mayor elemento de un vector es aquel elemento que, tras ordenar el vector, ocupa la posición número k.

Por ejemplo, para averiguar el sexto mayor (3mayor) elemento del vector:v = (2, 3, 6, 8, 3, 4, 1, 5, 3, 5, 6, 1)

Lo ordenamos:v = (1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 8)

Y vemos que en la secta posición aparece el 3. El coste para el número de

comparaciones es:

Obsérvese que clasificando primero y eligiendo el valor después el orden es, en promedio n log n. En el caso peor el coste será n2

21

Page 22: TEMA 2. Clasificación en memoria principal

MODULE ClasificacionParticion;FROM InOut IMPORT WriteInt, WriteLn, WriteString;

TYPE tipoarray=ARRAY[0..9] OF INTEGER;

VAR i,n: INTEGER;VAR a: tipoarray;

(* Procedimiento auxiliar *)PROCEDURE ordena (L, R : INTEGER);

VARi,j,k: INTEGER;piv,aux: INTEGER;

BEGINi:=L; j:=R;piv:=a[(L+R)DIV 2]; (* pivote *)REPEAT

WHILE (a[i] < piv) DO i := i+1; END;WHILE (piv < a[j]) DO j := j-1; END;IF i <= j THEN

aux:=a[i]; a[i]:=a[j]; a[j]:=aux; (*intercambio*)i:=i+1;j:=j1

END;UNTIL i>j;IF L<j THEN ordena(L,j) END;IF i<R THEN ordena(i,R) END;

END ordena;(* Fin Procedimiento auxiliar *)

BEGIN(* Carga del arreglo de prueba en orden inverso (peor caso) *)n:=9;FOR i:=1 TO 9 DO a[i]:=10-i; END;

(* Algoritmo de clasificación *)ordena (1,n);(* Fin Algoritmo de clasificación *)

(* Muestra el arreglo de prueba clasificado *)FOR i:=1 TO n DO WriteInt(a[i],4); END; WriteLn;

END ClasificacionParticion.

22

Page 23: TEMA 2. Clasificación en memoria principal

COMPARACIÓN DE LOS MÉTODOS AVANZADOS DE CLASIFICACIÓNLa clasificación rápida (Quick Sort) demuestra un magnífico comportamiento en los

casos mejor y promedio pero no es la solución definitiva ni relega los otros métodos de clasificación. En el peor caso, es deficiente por lo que cuando las llaves son muy parecidas en valor será aconsejable otro método, como por ejemplo la clasificación por montón.

Aunque los métodos avanzados presentan unos costes computacionales claramente inferiores a los directos, no son los más eficaces para todo n. Los métodos avanzados requieren más operaciones auxiliares que los directos y debe recordarse que los análisis realizados son asintóticos, por lo que para n pequeño son preferibles los métodos directos ya que en este entorno la diferencia entre los órdenes (n2) y (n log n) no es muy significativa y las operaciones auxiliares de los avanzados hacen que estos últimos sean menos eficaces.

CONCLUSIONESEn este capítulo se han presentado los métodos más conocidos para la clasificación

sobre arreglos. En general, los métodos de clasificación de inserción, selección e intercambio directo, y sus mejoras, se aplican cuando el número de datos no es muy elevado.

Por otra parte, los métodos de clasificación avanzados, son sofisticaciones de las ideas en las que se basan los directos, y aunque su análisis muestra que mejoran los costes de los directos sólo se aplican cuando el número de datos a clasificar es elevado. Esto es debido a que en caso contrario las operaciones auxiliares, que no son evaluadas en un análisis asintótico, afectan sensiblemente al coste total de la implementación haciendo que los directos sean más efectivos.

En cualquier caso, cuando sea necesario decidir qué método de clasificación sobre arreglos se va a aplicar en una situación práctica es imprescindible recordar el análisis realizado para ellos y contrastarlo con la información que se tenga de los datos. Por ejemplo, si la cantidad de datos es elevada y se sabe que el número de datos con llaves iguales es significativo, la clasificación rápida sería desaconsejable ya que estaríamos en una situación cercana al peor de los casos, y en ella ya se ha mostrado que el coste de este método es alto. En conclusión, siempre es conveniente reflexionar brevemente sobre la idoneidad de un método atendiendo a sus costes computacionales.

23