Ordenamiento

27
Ordenamiento Estructuras de datos

description

Ordenamiento. Estructuras de datos. Antecedentes. Un archivo de tamaño n es una secuencia de elementos r [0], r [1], …, r [ n -1], a cada elemento del archivo se le llama registro . A cada registro r [ i ] se le asocia una clave o llave k [ i ]. - PowerPoint PPT Presentation

Transcript of Ordenamiento

Page 1: Ordenamiento

Ordenamiento

Estructuras de datos

Page 2: Ordenamiento

Antecedentes

Un archivo de tamaño n es una secuencia de elementos r[0], r[1], …, r[n-1], a cada elemento del archivo se le llama registro.

A cada registro r[i] se le asocia una clave o llave k[i].

Se dice que el archivo está ordenado de acuerdo a la llave, si i<j implica que k[i] precede a k[j] para algún ordenamiento de las llaves.

Un ordenamiento es interno si los registros están en la memoria principal, o externo si se encuentran en almacenamiento auxiliar.

Una técnica de ordenamiento es estable si para todos los registros i y j tales que k[i] = k[j], si r[i] precede a r[j] en el archivo original, entonces r[i] precede a r[j] en el archivo ordenado.

Un ordenamiento ocurre ya sea sobre los mismos registros o sobre una tabla auxiliar de apuntadores (ordenamiento por dirección).

Page 3: Ordenamiento

4 DDD

2 BBB

1 AAA

5 EEE

3 CCC

llaves Otros campos

Registro 1

Registro 2

Registro 3

Registro 4

Registro 5

4 DDD

2 BBB

1 AAA

5 EEE

3 CCC

Archivo original Archivo ordenado

4 DDD

2 BBB

1 AAA

5 EEE

3 CCC

Tabla original de apuntadores

Registro 1

Registro 2

Registro 3

Registro 4

Registro 5

Tabla ordenada de apuntadores

Page 4: Ordenamiento

Eficiencia

Para elegir el método de ordenación se deben considerar los siguientes aspectos

Tiempo que se debe invertir para codificar el programa

La cantidad de tiempo de ejecución

El espacio necesario en memoria para ejecutar el programa

Page 5: Ordenamiento

Orden de ejecución

n a=0.01n^2 b=10n a+b (a+b)/n^2

10 1 100 101 1.01

50 25 500 525 0.21

100 100 1000 1100 0.11

500 2500 5000 7500 0.03

1000 10000 10000 20000 0.02

5000 250000 50000 300000 0.012

10000 1000000 100000 1100000 0.011

50000 25000000 500000 25500000 0.0102

100000 100000000 1000000 101000000 0.0101

500000 2500000000 5000000 2505000000 0.01002

Page 6: Ordenamiento

Comparación de orden de ejecución de funciones típicas

n n log n n^2

10 10 100

50 85 2500

100 200 10000

500 1349 250000

1000 3000 1000000

5000 18495 25000000

10000 40000 100000000

50000 234949 2500000000

100000 500000 1E+10

500000 2849485 2.5E+11

1000000 6000000 1E+12

5000000 33494850 2.5E+13

10000000 70000000 1E+14

Page 7: Ordenamiento

Métodos de ordenación

Existen tres formas básicas:

1. Ordenación por inserción. 2. Ordenación por selección. 3. Ordenación por intercambio.

Estudiaremos una algoritmo simple y otro complejo de cada técnica.

Page 8: Ordenamiento

Inserción directa

44 55 12 42 94 18 06 67

i=2 44 55 12 42 94 18 06 67

i=3 12 44 55 42 94 18 06 67

i=4 12 42 44 55 94 18 06 67

i=5 12 42 44 55 94 18 06 67

i=6 12 18 42 44 55 94 06 67

i=7 06 12 18 42 44 55 94 67

i=8 06 12 18 42 44 55 67 94

Se selecciona la llave más pequeña y se inserta en el lugar adecuado.

Page 9: Ordenamiento

Algoritmo en Cvoid InsercionDirecta(){ int i,j:indice; item x, y; for(i = 1; i<n; i++){ x = a[i]; y = x; j = i-1; while(j>=0&&x<a[j]){ a[j+1] = j>=0?a[j]:y; j = j-1; } a[j+1] = x; }}

Page 10: Ordenamiento

RendimientoEl número de comparaciones y movimientos es el siguiente:

Cmin = n – 1 Mmin = 2(n – 1) Cmed = (n2 + n – 2)/4 Mmed = (n2 + 9n – 10)/4 Cmax = (n2 + n) – 1 Mmax = (n2 + 3n – 4)

Page 11: Ordenamiento

Selección directa

44 55 12 42 94 18 06 67

06 55 12 42 94 18 44 67

06 12 55 42 94 18 44 67

06 12 18 42 94 55 44 67

06 12 18 42 94 55 44 67

06 12 18 42 44 55 94 67

06 12 18 42 44 55 94 67

06 12 18 42 44 55 67 94

Se selecciona el elemento con menor clave y se intercambia con el primero, luego por el segundo, y así sucesivamente.

Page 12: Ordenamiento

Código en C

void SeleccionDirecta(int a[],int n){ int i,j,k; int x; for(i= 0;i<n-1;i++){ k = i; x = a[i]; for(j = i+1;j<n;j++) if(a[j]<x){ k = j; x = a[j]; } a[k] = a[i]; a[i] = x; }}

Page 13: Ordenamiento

Rendimiento Número de comparaciones:

C = (n*n - n)/2

Número de movimientos:

Mmin = 3(n - 1) Mmed = n(ln n + ) Mmax = trunc(n2/4) + 3(n - 1)

Page 14: Ordenamiento

Intercambio directo (burbuja)

i=2 i=3 i=4 i=5 i=6 i=7 i=844 06 06 06 06 06 06 0655 44 12 12 12 12 12 1212 55 44 18 18 18 18 1842 12 55 44 42 42 42 4294 42 18 55 44 44 44 4418 94 42 42 55 55 55 5506 18 94 67 67 67 67 6767 67 67 94 94 94 94 94

Se intercambian los valores consecutivos del archivo comenzando por el final y se repite hasta haber intercambiado todos los elementos

Page 15: Ordenamiento

Código en C

void Burbuja(int a[],int n){ int i,j,x; for(i = 1;i<n;i++){ for(j = n-1;j>=i;j--) if(a[j-1]>a[j]){ x = a[j-1]; a[j-1] = a[j]; a[j] = x; } }}

Page 16: Ordenamiento

La sacudidaUna mejora de la burbuja es la sacudida. Consiste en cambiar el orden de recorrido en cada paso de la burbuja.

iz=2 3 3 4 4 de=8 8 7 7 4 44 06 06 06 06 55 44 44 12 12 12 55 12 44 18 42 12 42 18 42 94 42 55 42 44 18 94 18 55 55 06 18 67 67 67 67 67 94 94 94

Page 17: Ordenamiento

Eficiencia

El número de comparaciones es:

C = 3/4(n2 – n)

El número de movimientos es:

Mmin = 0Mmed = 3(n2 – n)/4Mmax = 3(n2 – n)/2

Page 18: Ordenamiento

Código en C

void Sacudida(int a[],int n){ int j,k,iz,de,x; iz = 1; de = n-1; k = n; do{ for(j=de;j>=iz;j--) if(a[j-1]>a[j]){ x = a[j-1]; a[j-1] = a[j]; a[j] = x; k = j; }

iz = k+1; for(j = iz; j<=de;j++) if(a[j-1]>a[j]){ x = a[j-1]; a[j-1] = a[j]; a[j] = x; k = j; } de = k-1; }while(iz<=de);}

Page 19: Ordenamiento

Ordenamiento de ShellEl método es similar al de inserción directa, la variante es que se realiza con intervalos decresientes hasta hacerlo de 1 en 1.

44 55 12 42 94 18 06 67

44 18 06 42 94 55 12 67

06 18 12 42 44 55 94 67

06 12 18 42 44 55 67 94

Page 20: Ordenamiento

EficienciaLa eficiencia del algoritmo depende en gran medida de la elección de los incrementos utilizados.

Knuth recomienda la secuencia: 1, 4, 13, 40, 121, … donde

hk–1= 3hk + 1, ht = 1 y t = log3 n – 1

También la secuencia: 1, 3, 7, 15, 31, … donde

hk–1= 2hk + 1, ht = 1 y t = log2 n – 1

El algoritmo tiene un comportamiento proporcional a n1.2.

Page 21: Ordenamiento

Código en Cvoid Shell(int a[],int n){ int incr,i,j,k,span,y,ninc,*inc; ninc = (int)(log(n)/log(3)-1); inc = (int*)malloc(ninc*sizeof(int)); inc[ninc-1] = 1; for(i=ninc-1;i>0;i--) inc[i-1] = 3*inc[i]+1; for(incr=0;incr<ninc;incr++){ span = inc[incr]; for(j = span;j<n;j++){ y = a[j]; for(k = j-span;k>=0 and y<a[k];k -= span) a[k+span] = a[k]; a[k+span] = y; } }}

Page 22: Ordenamiento

Ordenamiento del peine

El ordenamiento del peine es una mejora respecto al de la burbuja.

Se ejecuta la burbuja con incrementos decrecientes.

El incremento inicial se sugiere que sea n/1.3, y a cada paso se divide entre 1.3 hasta tener incrementos iguales a 1.

A cada paso se ordenan los elementos separados por el incremento reduciendo el total de trabajo a realizar.

El último paso se ejecuta con incremento de una unidad asegurando que se ordenen los elementos que no estén en orden todavía,

Page 23: Ordenamiento

44 55 12 42 94 18 06 67

06 55 12 42 94 18 44 67

06 18 12 42 94 55 44 67

06 18 12 42 67 55 44 94

06 18 12 42 44 55 67 94

06 12 18 42 44 55 67 94

Page 24: Ordenamiento

Código en C

void CombSort(int a[],int n){ int gap,i,j,h; bool swap; gap = n; do{ gap = (int)(gap/1.3); if(gap<1) gap = 1; swap = false;

for(i = 1;i<n-gap;i++){ j = i+gap; if(a[i]>a[j]){ h = a[i]; a[i] = a[j]; a[j] = h; swap = swap+1; } } }while((swap)and(gap>1));}

Page 25: Ordenamiento

EL rápidoEl método rápido (quick Sort) se basa en la partición de un arreglo, esta consiste en elegir el elemento de la mitad y colocar todos los elementos más pequeños que él a la izquierda y los más grandes a la derecha. 44 55 12 42 94 06 18 67

18 06 12 42 94 55 44 67 El proceso se repite para la parte izquierda y derecha de la partición, y re repite recursivamente hasta tener el arreglo ordenado.

Page 26: Ordenamiento

Código en Cvoid rapido(int a[],int iz, int de){ int i,j,x,w; i = iz; j = de; x = a[(iz+de)/2]; do{ while(a[i]<x) i++; while(x<a[j]) j--; if(i<=j){ w = a[i]; a[i] = a[j]; a[j] = w; i++; j--; } }while(i<=j);

if(iz<j) rapido(a,iz,j); if(i<de) rapido(a,i,de);}

Page 27: Ordenamiento

Eficiencia

El rápido tiene un comportamiento proporcional a n log n.

Desgraciadamente en el peor de los casos pude tener un comportamiento proporcional a n2.