ordenamiento de datos

33
Algoritmo de ordenamiento Quicksort en acción sobre una lista de números aleatorios. Las líneas horizontales son valores pivote. En computación y matemáticas un algoritmo de ordenamiento es un algoritmo que pone elementos de una lista o un vector en una secuencia dada por una relación de orden , es decir, el resultado de salida ha de ser una permutación —o reordenamiento— de la entrada que satisfaga la relación de orden dada. Las relaciones de orden más usadas son el orden numérico y el orden lexicográfico . Ordenamientos eficientes son importantes para optimizar el uso de otros algoritmos (como los de búsqueda y fusión) que requieren listas ordenadas para una ejecución rápida. También es útil para poner datos en forma canónica y para generar resultados legibles por humanos. Desde los comienzos de la computación, el problema del ordenamiento ha atraído gran cantidad de investigación, tal vez debido a la complejidad de resolverlo eficientemente a pesar de su planteamiento simple y familiar. Por ejemplo, BubbleSort fue analizado desde 1956. 1 Aunque muchos puedan considerarlo un problema resuelto, nuevos y útiles algoritmos de ordenamiento se siguen inventado hasta el día de hoy (por ejemplo, elordenamiento de biblioteca se publicó por primera vez en el 2004). Los algoritmos de ordenamiento son comunes en las clases introductorias a la computación, donde la abundancia de algoritmos para el problema proporciona una gentil introducción a la variedad de conceptos núcleo de los algoritmos, como notación de O mayúscula , algoritmos divide y vencerás , estructuras de datos , análisis de los casos peor, mejor, y promedio , y límites inferiores.

Upload: arnoldoylulu-rodas-hernandez

Post on 06-Aug-2015

168 views

Category:

Documents


5 download

DESCRIPTION

Programas en java

TRANSCRIPT

Page 1: ORDENAMIENTO DE DATOS

Algoritmo de ordenamiento

Quicksort en acción sobre una lista de números aleatorios. Las líneas horizontales son valores pivote.

En computación y matemáticas un algoritmo de ordenamiento es un algoritmo que pone elementos de

una lista o un vector en una secuencia dada por una relación de orden, es decir, el resultado de salida

ha de ser una permutación —o reordenamiento— de la entrada que satisfaga la relación de orden dada.

Las relaciones de orden más usadas son el orden numérico y el orden lexicográfico. Ordenamientos

eficientes son importantes para optimizar el uso de otros algoritmos (como los de búsqueda y fusión)

que requieren listas ordenadas para una ejecución rápida. También es útil para poner datos en forma

canónica y para generar resultados legibles por humanos.

Desde los comienzos de la computación, el problema del ordenamiento ha atraído gran cantidad de

investigación, tal vez debido a la complejidad de resolverlo eficientemente a pesar de su planteamiento

simple y familiar. Por ejemplo, BubbleSort fue analizado desde 1956.1 Aunque muchos puedan

considerarlo un problema resuelto, nuevos y útiles algoritmos de ordenamiento se siguen inventado

hasta el día de hoy (por ejemplo, elordenamiento de biblioteca se publicó por primera vez en el 2004).

Los algoritmos de ordenamiento son comunes en las clases introductorias a la computación, donde la

abundancia de algoritmos para el problema proporciona una gentil introducción a la variedad de

conceptos núcleo de los algoritmos, como notación de O mayúscula, algoritmos divide y

vencerás, estructuras de datos, análisis de los casos peor, mejor, y promedio, y límites inferiores.

Contenido

  [ocultar]

1 Clasificación

2 Estabilidad

3 Lista de algoritmos de ordenamiento

Page 2: ORDENAMIENTO DE DATOS

4 Referencias

5 Enlaces externos

[editar]Clasificación

Los algoritmos de ordenamiento se pueden clasificar de las siguientes maneras:

La más común es clasificar según el lugar donde se realice la ordenación

Algoritmos de ordenamiento interno : en la memoria del ordenador.

Algoritmos de ordenamiento externo : en un lugar externo como un disco duro.

Por el tiempo que tardan en realizar la ordenación, dadas entradas ya ordenadas o inversamente

ordenadas:

Algoritmos de ordenación natural : Tarda lo mínimo posible cuando la entrada está ordenada.

Algoritmos de ordenación no natural : Tarda lo mínimo posible cuando la entrada está

inversamente ordenada.

Por estabilidad: un ordenamiento estable mantiene el orden relativo que tenían originalmente los

elementos con claves iguales. Por ejemplo, si una lista ordenada por fecha se reordena en orden

alfabético con un algoritmo estable, todos los elementos cuya clave alfabética sea la misma

quedarán en orden de fecha. Otro caso sería cuando no interesan las mayúsculas y minúsculas,

pero se quiere que si una clave aBC estaba antes que AbC, en el resultado ambas claves

aparezcan juntas y en el orden original: aBC, AbC. Cuando los elementos son indistinguibles

(porque cada elemento se ordena por la clave completa) la estabilidad no interesa. Los algoritmos

de ordenamiento que no son estables se pueden implementar para que sí lo sean. Una manera de

hacer esto es modificar artificialmente la clave de ordenamiento de modo que la posición original en

la lista participe del ordenamiento en caso de coincidencia.

Los algoritmos se distinguen por las siguientes características:

Complejidad computacional  (peor caso, caso promedio y mejor caso) en términos de n, el tamaño

de la lista o arreglo. Para esto se usa el concepto de orden de una función y se usa la notaciónO(n).

El mejor comportamiento para ordenar (si no se aprovecha la estructura de las claves) es

O(n log n). Los algoritmos más simples son cuadráticos, es decir O(n²). Los algoritmos que

aprovechan la estructura de las claves de ordenamiento (p. ej. bucket sort) pueden ordenar en

O(kn) donde k es el tamaño del espacio de claves. Como dicho tamaño es conocido a priori, se

puede decir que estos algoritmos tienen un desempeño lineal, es decir O(n).

Uso de memoria y otros recursos computacionales. También se usa la notación O(n).

Page 3: ORDENAMIENTO DE DATOS

[editar]Estabilidad

Los algoritmos de ordenamiento estable mantienen un relativo preorden total. Esto significa que un

algoritmo es estable solo cuando hay dos registros R y S con la misma clave y con R apareciendo antes

que S en la lista original.

Cuando elementos iguales (indistinguibles entre sí), como números enteros, o más generalmente,

cualquier tipo de dato en donde el elemento entero es la clave, la estabilidad no es un problema. De

todas formas, se asume que los siguientes pares de números están por ser ordenados por su primer

componente:

(4, 1) (3, 7) (3, 1) (5, 6)

En este caso, dos resultados diferentes son posibles, uno de los cuales mantiene un orden relativo de

registros con claves iguales, y una en la que no:

(3, 7) (3, 1) (4, 1) (5, 6) (orden mantenido)

(3, 1) (3, 7) (4, 1) (5, 6) (orden cambiado)

Los algoritmos de ordenamiento inestable pueden cambiar el orden relativo de registros con claves

iguales, pero los algoritmos estables nunca lo hacen. Los algoritmos inestables pueden ser

implementados especialmente para ser estables. Una forma de hacerlo es extender artificialmente el

cotejamiento de claves, para que las comparaciones entre dos objetos con claves iguales sean

decididas usando el orden de las entradas original. Recordar este orden entre dos objetos con claves

iguales es una solución poco práctica, ya que generalmente acarrea tener almacenamiento adicional.

Ordenar según una clave primaria, secundaria, terciara, etc., puede ser realizado utilizando cualquier

método de ordenamiento, tomando todas las claves en consideración (en otras palabras, usando una

sola clave compuesta). Si un método de ordenamiento es estable, es posible ordenar múltiples ítems,

cada vez con una clave distinta. En este caso, las claves necesitan estar aplicadas en orden de

aumentar la prioridad.

Ejemplo: ordenar pares de números, usando ambos valores

(4, 1) (3, 7) (3, 1) (4, 6) (original)

(4, 1) (3, 1) (4, 6) (3, 7) (después de ser ordenado por el segundo

valor)

Page 4: ORDENAMIENTO DE DATOS

(3, 1) (3, 7) (4, 1) (4, 6) (después de ser ordenado por el primer

valor)

Por otro lado:

(3, 7) (3, 1) (4, 1) (4, 6) (después de ser ordenado por el primer

valor)

(3, 1) (4, 1) (4, 6) (3, 7) (después de ser ordenando por el segundo

valor,

el orden por el primer valor es

perturbado)

[editar]Lista de algoritmos de ordenamiento

Algunos algoritmos de ordenamiento agrupados según estabilidad tomando en cuenta la complejidad

computacional.

Estables

Nombre traducido Nombre original ComplejidadMemoria

Método

Ordenamiento de burbuja Bubblesort O(n²) O(1) Intercambio

Ordenamiento de burbuja bidireccional

Cocktail sort O(n²) O(1) Intercambio

Ordenamiento por inserción Insertion sort O(n²) O(1) Inserción

Ordenamiento por casilleros Bucket sort O(n) O(n)No comparativo

Ordenamiento por cuentas Counting sort O(n+k) O(n+k)No comparativo

Ordenamiento por mezcla Merge sort O(n log n) O(n) Mezcla

Page 5: ORDENAMIENTO DE DATOS

Ordenamiento con árbol binario Binary tree sort O(n log n) O(n) Inserción

Pigeonhole sort O(n+k) O(k)

Ordenamiento Radix Radix sort O(nk) O(n)No comparativo

Distribution sort O(n³) versión recursiva O(n²)

Gnome sort O(n²)

Inestables

Nombre traducido Nombre original ComplejidadMemoria

Método

Ordenamiento Shell Shell sort O(n1.25) O(1) Inserción

Comb sort O(n log n) O(1) Intercambio

Ordenamiento por selección Selection sort O(n²) O(1) Selección

Ordenamiento por montículos Heapsort O(n log n) O(1) Selección

Smoothsort O(n log n) O(1) Selección

Ordenamiento rápido QuicksortPromedio: O(n log n),peor caso: O(n²)

O(log n) Partición

Several Unique Sort

Promedio: O(n u),peor caso: O(n²);u=n; u = número único de registros

Cuestionables, imprácticos

Page 6: ORDENAMIENTO DE DATOS

Nombre traducido Nombre original ComplejidadMemoria

Método

Bogosort O(n × n!), peor: no termina

Pancake sortingO(n), excepto enmáquinas de Von Neumann

Randomsort

[editar]Referencias

1. ↑  Bubble Sort: An archaeological algorithm analysis. Owen Astrachan

[editar]Enlaces externos

Explicación de los distintos métodos de ordenamiento en Java.  (pdf)

Discusión sobre varios algoritmos de ordenación y sus características  (licencia GFDL) (pdf)

Animación de algoritmos de ordenamiento

Animación de algoritmos de ordenamiento (en inglés)

ALT: Algorithm Learning Tool. Herramienta de apoyo a la enseñanza de algoritmos que muestra

gráficamente su funcionamiento. Permite implementar algoritmos propios y realizar una ejecución

dinámica e interactiva

Códigos de Ordenamiento en Python

Page 7: ORDENAMIENTO DE DATOS

Algoritmos de Ordenamiento 

Debido a que las estructuras de datos son utilizadas para almacenar información, para poder recuperar esa información de manera eficiente es deseable que aquella esté ordenada. Existen varios métodos para ordenar las diferentes estructuras de datos básicas.En general los métodos de ordenamiento no son utilizados con frecuencia, en algunos casos sólo una vez. Hay métodos muy simples de implementar que son útiles en los casos en dónde el número de elementos a ordenar no es muy grande (ej, menos de 500 elementos). Por otro lado hay métodos sofisticados, más difíciles de implementar pero que son más eficientes en cuestión de tiempo de ejecución.Los métodos sencillos por lo general requieren de aproximadamente n x n pasos para ordenar n elementos.Los métodos simples son: insertion sort (o por inserción directa) selection sort, bubble sort, y shellsort, en dónde el último es una extensón al insertion sort, siendo más rápido. Los métodos más complejos son el quick-sort, el heap sort, radix y address-calculation sort. El ordenar un grupo de datos significa mover los datos o sus referencias para que queden en una secuencia tal que represente un orden, el cual puede ser numérico, alfabético o incluso alfanumérico, ascendente o descendente.Se ha dicho que el ordenamiento puede efectuarse moviendo los registros con las claves. El mover un registo completo implica un costo, el cual se incrementa conforme sea mayor el tamaño del registro. Es por ello que es deseable evitar al máximo el movimiento de los registros. Una alternativa es el crear una tabla de referencias a los registros y mover las referencias y no los datos. A continuación se mostrarán los métodos de ordenamiento empezando por el más sencillo y avanzando hacia los mas sofisticados La eficiencia de los algoritmos se mide por el número de comparaciones e intercambios que tienen que hacer, es decir, se toma n como el número de elementos que tiene el arreglo a ordenar y se dice que un algoritmo realiza O(n2) comparaciones cuando compara n veces los n elementos, n x n = n2.

Análisis de Algoritmos Notación de Orden

Una función f(n) se define de orden O(g(n)), es decir, f(n) = O(g(n)) si existen constantes positivas n0 y c tales que:

Page 8: ORDENAMIENTO DE DATOS

| f(n) | = c * <= | g(n) | , para toda n > n0

100 n3 => O(n3)

6n2 + 2n + 4 => O(n2)

1024 => O(1)

1+2+3+4+...+n-1+n= n * (n+1)/2 = O(n2)

Insertion Sort

Este es uno de los métodos más sencillos. Consta de tomar uno por uno los elementos de un arreglo y recorrerlo hacia su posición con respecto a los anteriormente ordenados. Así empieza con el segundo elemento y lo ordena con respecto al primero. Luego sigue con el tercero y lo coloca en su posición ordenada con respecto a los dos anteriores, así sucesivamente hasta recorrer todas las posiciones del arreglo. Este es el algoritmo:

Procedimiento Insertion Sort

Este procedimiento recibe el arreglo de datos a ordenar a[] y altera las posiciones de sus elementos hasta dejarlos ordenados de menor a mayor. N representa el número de elementos que contiene a[].

paso 1: [Para cada pos. del arreglo] For i <- 2 to N dopaso 2: [Inicializa v y j] v <- a[i]

j <- i.paso 3: [Compara v con los anteriores] While a[j-1] > v AND j>1 dopaso 4: [Recorre los datos mayores] Set a[j] <- a[j-1],paso 5: [Decrementa j] set j <- j-1.paso 5: [Inserta v en su posición] Set a[j] <- v.paso 6: [Fin] End.

Ejemplo:

Si el arreglo a ordenar es a = ['a','s','o','r','t','i','n','g','e','x','a','m','p','l','e'],

el algoritmo va a recorrer el arreglo de izquierda a derecha. Primero toma el segundo dato 's' y lo asigna a v y i toma el valor de la posición actual de v.

Page 9: ORDENAMIENTO DE DATOS

Luego compara esta 's' con lo que hay en la posición j-1, es decir, con 'a'. Debido a que 's' no es menor que 'a' no sucede nada y avanza i.

Ahora v toma el valor 'o' y lo compara con 's', como es menor recorre a la 's' a la posición de la 'o'; decrementa j, la cual ahora tiene la posición en dónde estaba la 's'; compara a 'o' con a[j-1] , es decir, con 'a'. Como no es menor que la 'a' sale del for y pone la 'o' en la posición a[j]. El resultado hasta este punto es el arreglo siguiente: a = ['a','o','s','r',....]

Así se continúa y el resultado final es el arreglo ordenado :

a = ['a','a','e','e','g','i','l','m','n','o','p','r','s','t','x']

 

Selection Sort

El método de ordenamiento por selección consiste en encontrar el menor de todos los elementos del arreglo e intercambiarlo con el que está en la primera posición. Luego el segundo mas pequeño, y así sucesivamente hasta ordenar todo el arreglo.

 

Procedimiento Selection Sort

paso 1: [Para cada pos. del arreglo] For i <- 1 to N dopaso 2: [Inicializa la pos. del menor] menor <- ipaso 3: [Recorre todo el arreglo] For j <- i+1 to N dopaso 4: [Si a[j] es menor]

If a[j] < a[menor] thenpaso 5: [Reasigna el apuntador al menor] min = jpaso 6: [Intercambia los datos de la pos.

min y posición i] Swap(a, min, j).paso 7: [Fin] End.

Ejemplo:

El arreglo a ordenar es a = ['a','s','o','r','t','i','n','g','e','x','a','m','p','l','e']. Se empieza por recorrer el arreglo hasta encontrar el menor elemento. En este caso el menor elemento es la primera 'a'. De manera que no ocurre ningún cambio. Luego se

Page 10: ORDENAMIENTO DE DATOS

procede a buscar el siguiente elemento y se encuentra la segunda 'a'. Esta se intercambia con el dato que está en la segunta posición, la 's', quedando el arreglo así después de dos recorridos: a = ['a','a','o','r','t','i','n','g','e','x','s','m','p','l','e'].

El siguiente elemento, el tercero en orden de menor mayor es la primera 'e', la cual se intercambia con lo que está en la tercera posición, o sea, la 'o'. Le sigue la segunda 's', la cual es intercambiada con la 'r'. El arreglo ahora se ve de la siguiente manera: a = ['a','a','e','e','t','i','n','g','o','x','s','m','p','l','r']. De esta manera se va buscando el elemento que debe ir en la siguiente posición hasta ordenar todo el arreglo.

El número de comparaciones que realiza este algoritmo es :

para el primer elemento se comparan n-1 datos, en general para el elemento i-ésimo se hacen n-i comparaciones, por lo tanto, el total de comparaciones es:

la sumatoria para i de 1 a n-1 (n-i) = 1/2 n (n-1).

 

Shellsort

Denominado así por su desarrollador Donald Shell (1959), ordena una estructura de una manera similar a la del Bubble Sort, sin embargo no ordena elementos adyacentes sino que utiliza una segmentación entre los datos. Esta segmentación puede ser de cualquier tamaño de acuerdo a una secuencia de valores que empiezan con un valor grande (pero menor al tamaño total de la estructura) y van disminuyendo hasta llegar al '1'. Una secuencia que se ha comprobado ser de las mejores es: ...1093, 364, 121, 40, 13, 4, 1. En contraste, una secuencia que es mala porque no produce un ordenamiento muy eficiente es ...64, 32, 16, 8, 4, 2, 1.

Su complejidad es de O(n1.2) en el mejor caso y de O(n1.25) en el caso promedio.

 

void shellsort ( int a[], int n)/* Este procedimiento recibe un arreglo a ordenar a[] y el tamaño del arreglo n. Utiliza en este caso una serie de t=6 incrementos h=[1,4,13,40,121,364] para el proceso (asumimos que el arreglo no es muy grande). */{

int x,i,j,inc,s;

Page 11: ORDENAMIENTO DE DATOS

for(s=1; s < t; s++) /* recorre el arreglo de incrementos */{

inc = h[s];for(i=inc+1; i < n; i++) {

x = a[i];j = i-inc;while( j > 0 && a[j] > x){

a[j+h] = a[j];j = j-h;

}a[j+h] = x;

}}

}

 

Bubble Sort

El bubble sort, también conocido como ordenamiento burbuja, funciona de la siguiente manera: Se recorre el arreglo intercambiando los elementos adjacentes que estén desordenados. Se recorre el arreglo tantas veces hasta que ya no haya cambios. Prácticamente lo que hace es tomar el elemento mayor y lo va recorriendo de posición en posición hasta ponerlo en su lugar.

Procedimiento Bubble Sort

paso 1: [Inicializa i al final de arreglo] For i <- N downto 1 dopaso 2: [Inicia desde la segunda pos.] For j <- 2 to i dopaso 4: [Si a[j-1] es mayor que el que le sigue] If a[j-1] < a[j] thenpaso 5: [Los intercambia] Swap(a, j-1, j).paso 7: [Fin] End.

Tiempo de ejecución del bubble sort:

para el mejor caso (un paso) O(n) peor caso n(n-1)/2 promedio O(n2)

Page 12: ORDENAMIENTO DE DATOS

 

Merge Sort

El método Quicksort divide la estructura en dos y ordena cada mitad recursivamente. El caso del MergeSort es el opuesto, es decir, en éste método de unen dos estructuras ordenadas para formar una sola ordenada correctamente.

Tiene la ventaja de que utiliza un tiempo proporcional a: n log (n), su desventaja radica en que se requiere de un espacio extra para el procedimiento.

Este tipo de ordenamiento es útil cuando se tiene una estructura ordenada y los nuevos datos a añadir se almacenan en una estructura temporal para después agregarlos a la estructura original de manera que vuelva a quedar ordenada.

Procedimiento MergeSort

/*recibe el arreglo a ordenar un índice l que indica el límite inferior del arreglo a ordenar y un índice r que indica el límite superior*/

void mergesort(int a[], int l, int r){

int i,j,k,m,b[MAX];if (r > l) {

m = (r+l) /2;mergesort(a, l, m);mergesort(a, m+1, r);for (i= m+1; i > l;i--)

b[i-1] = a[i-1];for (j= m; j < r;j++)

b[r+m-j] = a[j+1];for (k=l ; k <=r; k++)

if(b[i] < b[j]) a[k] = b[i++];else a[k] = b[j--];

}}

a = {a,s,o,r,t,i,n,g,e,x,a,m,p,l,e} {a,s, o,r, a,o,r,s, i,t, g,n, g,i,n,t, a,g,i,n,o,r,s,t, e,x, a,m,

Page 13: ORDENAMIENTO DE DATOS

a,e,m,x, l,p, e,l,p} a,e,e,l,m,p,x}

a = {a,a,e,e,g,i,l,m,n,o,p,r,s,t,x}

Heap Sort

Este método garantiza que el tiempo de ejecución siempre es de:

O(n log n)

El significado de heap en ciencia computacional es el de una cola de prioridades (priority queue). Tiene las siguientes características:

Un heap es un arreglo de n posiciones ocupado por los elementos de la cola. (Nota: se utiliza un arreglo que inicia en la posición 1 y no en cero, de tal manera que al implementarla en C se tienen n+1 posiciones en el arreglo.)

Se mapea un árbol binario de tal manera en el arreglo que el nodo en la posición i es el padre de los nodos en las posiciones (2*i) y (2*i+1).

El valor en un nodo es mayor o igual a los valores de sus hijos. Por consiguiente, el nodo padre tiene el mayor valor de todo su subárbol.

Heap Sort consiste ecencialmente en:

convertir el arreglo en un heap construir un arreglo ordenado de atrás hacia adelante (mayor a menor) repitiendo los

siguientes pasos:o sacar el valor máximo en el heap (el de la posición 1)o poner ese valor en el arreglo ordenadoo reconstruir el heap con un elemento menos

utilizar el mismo arreglo para el heap y el arreglo ordenado.

 

Procedimiento Heapsort

/* Recibe como parámetros un arreglo a ordenar y un entero que indica el numero de datros a ordenar */

void heapsort(int a[], int N){

int k;for(k=N/2; k>=1; k--)

downheap(a,N,k);while(N > 1){

Page 14: ORDENAMIENTO DE DATOS

swap(a,1,N);downheap(a,--N,1);

}}

/* el procedimiento downheap ordena el &aacure;rbol de heap para que el nodo padre sea mayor que sus hijos */

void downheap(int a[], int N, int r){

int j, v;v = a[r];while (r <= N/2){

j = 2*r;if(j < N && a[j] < a[j+1]);

j++;if( v >= a[j])

break;a[r] = a[j];r = j;

}a[r] = v;

}

 

 

Partition-Exchange Sort o Quicksort

Es un método de ordenamiento recursivo y en lenguajes en dónde no se permite la recursividad esto puede causar un retraso significativo en la ejecución del quicksort.

Su tiempo de ejecución es de n log2n en promedio.

void quicksort(int a[], int l, int r){

int i,j,v;if(r > l){

v = a[r];i = l-1;j = r;for(;;){

while(a[++i] < v && i < r);while(a[--j] > v && j > l);if( i >= j)

Page 15: ORDENAMIENTO DE DATOS

break;swap(a,i,j);

}swap(a,i,r);quicksort(a,l,i-1);quicksort(a,i+1,r);

}}

a = {a,s,o,r,t,i,n}

a i o r t s n

a i n r t s o

a i n o t s r

a i n o r s t

Page 16: ORDENAMIENTO DE DATOS

Ordenamiento de raíz (radix sort).

Este ordenamiento se basa en los valores de los dígitos reales en las representaciones de posiciones de los números que se ordenan.

Por ejemplo el número 235 se escribe 2 en la posición de centenas, un 3 en la posición de decenas y un 5 en la posición de unidades.

Reglas para ordenar.

Empezar en el dígito más significativo y avanzar por los dígitos menos significativos mientras coinciden los dígitos correspondientes en los dos números.

El número con el dígito más grande en la primera posición en la cual los dígitos de los dos números no coinciden es el mayor de los dos (por supuesto sí coinciden todos los dígitos de ambos números, son iguales).

Este mismo principio se toma para Radix Sort, para visualizar esto mejor tenemos el siguiente ejemplo. En el ejemplo anterior se ordeno de izquierda a derecha. Ahora vamos a ordenar de derecha a izquierda.

Archivo original.

25 57 48 37 12 92 86 33

 

 

Asignamos colas basadas en el dígito menos significativo.

Parte delantera Parte posterior

0

1

212 92

Page 17: ORDENAMIENTO DE DATOS

333

4

525

686

757 37

848

9

10

Después de la primera pasada:

12 92 33 25 86 57 37 48

Colas basadas en el dígito más significativo.

Parte delantera Parte posterior

0

112

225

333 37

448

557

6

7

886

992

Page 18: ORDENAMIENTO DE DATOS

10

Archivo ordenado: 12 25 33 37 48 57 86 92

A S O R T I N G E X A M P L E

A E O L M I N G E A X T P R S

A E A E G I N M L O

A A E E G

A A

A A

E E G

E E

I N M L O

L M N O

L M

N O

S T P R X

S R P T

P R S

R S

#include #include #define NUMELTS 20

void radixsort(int x[], int n){ int front[10], rear[10]; struct {

Page 19: ORDENAMIENTO DE DATOS

int info; int next; } node[NUMELTS]; int exp, first, i, j, k, p, q, y;

/* Inicializar una lista viculada */ for (i = 0; i < n-1; i++) { node[i].info = x[i]; node[i].next = i+1; } /* fin del for */ node[n-1].info = x[n-1]; node[n-1].next = -1; first = 0; /*first es la cabeza de la lista vinculada */ for (k = 1; k < 5; k++) { /* Suponer que tenemos n£meros de cuatro dÁgitos */ for (i = 0; i < 10; i++) { /*Inicializar colas */ rear[i] = -1; front[i] = -1; } /*fin del for */ /* Procesar cada elemento en la lista */ while (first != -1) { p = first; first = node[first].next; y = node[p].info; /* Extraer el kâsimo dÁgito */ exp = pow(10, k-1); /* elevar 10 a la (k-1)âsima potencia */ j = (y/exp) % 10; /* Insertar y en queue[j] */ q = rear[j]; if (q == -1)

front[j] = p; else

node[q].next = p; rear[j] = p; } /*fin del while */

/* En este punto, cada registro est en su cola bas ndose en el dÁgito k Ahora formar una lista £nica de todos los elementos de la cola. Encontrar el primer elemento. */ for (j = 0; j < 10 && front[j] == -1; j++); ; first = front[j];

/* Vincular las colas restantes */ while (j <= 9) { /*Verificar si se ha terminado */ /*Encontrar el elemento siguiente */ for (i = j+1; i < 10 && front[i] == -1; i++);

; if (i <= 9) {

p = i;node[rear[j]].next = front[i];

} /* fin del if */ j = i; } /* fin del while */

Page 20: ORDENAMIENTO DE DATOS

node[rear[p]].next = -1; } /* fin del for */

/* Copiar de regreso al archivo original */ for (i = 0; i < n; i++) { x[i] = node[first].info; first = node[first].next; } /*fin del for */} /* fin de radixsort*/

int main(void){ int x[50] = {NULL}, i; static int n;

printf("\nCadena de n£meros enteros: \n"); for (n = 0;; n++) if (!scanf("%d", &x[n])) break; if (n) radixsort (x, n); for (i = 0; i < n; i++) printf("%d ", x[i]); return 0;}

Estado de la lista

i Node[i].info Node[i].next

Inicialización K = 1 K = 2 K = 3

0 65 1 3 1 2

1 789 2 -1 -1 -1

2 123 3 0 3 3

3 457 -1 1 0 1

 

 

rear = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}

2 0 3 1

front = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}

2 0 3 1

Page 21: ORDENAMIENTO DE DATOS

 

 

k = 1

p = 0 p = 1 p = 2 p = 3

first = 1 first = 2 first = 3 first = -1

y = 65 y = 789 y = 123 y = 457

exp = 1 exp = 1 exp = 1 exp = 1

j = 5 j = 9 j = 3 j = 7

q = -1 q = -1 q = -1 q = -1

si q == -1 si q == -1 si q == -1 si q == -1

front[5] = 0 front[9] = 1 front[3] = 2 front[7] = 3

rear[5] = 0 rear[9] = 1 rear[3] = 2 rear[7] = 3

j = 3first = 2while ( j <= 9)

i = 5si i <= 9

p = 5 node[2].next = 0 j = 5 i = 7 si i <= 9 p = 7 node[0].next = 3 j = 5 i = 9 si i <= 9 p = 9 node[2].next = 1 j = 9

fin del whilep = 9node[1].next = -1

 

Page 22: ORDENAMIENTO DE DATOS

 

 

 

 

 

 

Características.

Debido a que el ciclo for (k = 1; k <= m; k++) externo se recorre m veces (una para cada dígito) y el ciclo interior n veces (una para cada elemento en el archivo) el ordenamiento es de aproximadamente (m*n).

Si las llaves son complejas (es decir, si casi cada número que puede ser una llave lo es en realidad) m se aproxima a log n, por lo que (m*n) se aproxima a (n logn).

Si la cantidad de dígitos es grande, en ocasiones es más eficiente ordenar el archivo aplicando primero el ordenamiento de raíz a los dígitos más significativos y después utilizando inserción directa sobre el archivo ordenado.

 

 

Ventajas.

El ordenamiento es razonablemente eficiente si el número de dígitos en las llaves no es demasiado grande.

Si las máquinas tienen la ventaja de ordenar los dígitos (sobre todo si están en binario) lo ejecutarían con mucho mayor rapidez de lo que ejecutan una comparación de dos llaves completas.

 

Page 23: ORDENAMIENTO DE DATOS

O rdenamiento por cálculo de dirección.

En este método, se aplica una función f a cada llave. El res ultado de esta función determina dentro de cuál entre varios archivos se va a colocar el registro. La función debe tener la propiedad de qie si x<=y,f(x),<=f(y). Esta función se denomina preservadora de orden .Por tanto, todos lo registros en un subarchivo tendrán llaves que sean menores que o iguales a las llaves de los registros en otros subarchivos. Un elemento se coloca en un subarchivo en secuencia correcta utilizando cualquier método de ordenam iento; con frecencia se utiliza la inserción simple. Después de que se han colocado todos los elementos del archivo original en subarchivos se concatenan para producir el resultado ordenado.

Por ejemplo, considerem os el archivo de muestra.

25 57 48 37 12 92 86 33

Vamos a crear 10 subarchivos,uno para cada uno de los 10 primeros dígitos posibles. Al principio , cada uno de estos subarchivos está vacío. Se declara un arreglo de apuntadores f[10], en donde f[i] apunta al primer elemento en el archivo cuyo dígito es i. Después de examinar el primer elemento (25), se coloca en el archiv o encabezado por f[2]. Cada uno de los subarchivos se conserva como una lista ligada ordenada de los elementos de arreglo originales. Después de procesar cada uno de los elementos en el archivo original, aparecen los subarchivos como se muestra a continuación.

Algoritmo de ordenamiento.

Presentamos una rutina para implementar el ordenamiento de cálculo de dirección. La rutina supone un arreglo de números de 2 dígitos y u tiliza el primer dígito de cada número para asignar cada número a un subarchivo.

 

#define N... /* N es el numero de elementos a ordenar*/

addr( int x[],int n){

int f[10],first,i,j,p,y;struct{

int info; int next; } node[N]

/* Inicializar la lista ligada disponible */for(i=0;i<n-1;i++)

node[i].next=i+1;

Page 24: ORDENAMIENTO DE DATOS

node[n-1].next=-1;

for(i=0;i<n;i++)node[i].info=x[i];

/* Inicializar los apuntadores */for(i=0;i<10;i++)

f[i]=-1;

for(i=0;i<n;i++) { /* Insertamos sucesivamente cada elemento en su */ /* subarchivo respectivo utilizando inserción de lista */ y=x[i]; first=y/10; /* Encontrar el dígito de las decenas */ /* Buscar en la lista ligada */ place(&f[first],y); /* place inserta "y" en su posición correcta en la lista */ /* a la que se apunta mediante f[first] */ }

/* Copiar los números de regreso al erreglo x */i=0;for(j=0;j<10;j++)

{p=f[j];

while(p!=-1) {

x[i++]=node[p].info; p=node[p].next; } }}

 

 

 

Programa de ordemaniento por cálculo de dirección.

 

#include <stdio.h>#include <conio.h>#define N 8

main(void){ int x[N],f[10];

Page 25: ORDENAMIENTO DE DATOS

int i,j,p,a,s,y,first; struct{

int info; int next;

}node[N]; clrscr();

for(i=0;i<N;i++) /*lectura del arreglo x[N] a ordenar*/ {

printf("x[%d]=",i); scanf("%d",&x[i]);

}

for(i=0;i<N-1;i++) /*Inicio de la lista disponible*/ node[i].next=i+; /*apuntadores*/ node[N-1].next=-1;

for(i=0;i<N;i++) /*dato*/ node[i].info=x[i];

for(i=0;i<10;i++) /*Inicialización de apuntadores f[10]*/ f[i]=-1; /*al principio f[i] no apunta a nada */

for(i=0;i<N;i++) /*Creación de sub-listas*/ {

y=x[i]; /*cálculo del digito de las decenas*/

first=y/10;if(f[first]==-1) /*f[first] no apunta a nigún

dato*/ {

f[first]=i;

node[i].next=-1;}else /* f[first] apunta

a un dato*/{

if(node[f[first]].next==-1) /*apunta al primer dato en lista*/

{if(node[f[first]].info < y) {

node[f[first]].next=i;

node[i].next=-1;} else{

node[i].next=f[first];node[f[first]].next=-1; f[first]=i;

Page 26: ORDENAMIENTO DE DATOS

} }else /*Se continua la

lista*/{

a=f[first]; /*a= anterior*/

s=node[a].next; /*s= siguiente*/

if(y<node[f[first]].info){

f[first]=i;node[i].next=a;

}else{

while(y>node[s].info&&s!=-1){

a=s; s=node[s].next;

}node[a].next=i;

/*i semejante a temp*/node[i].next=s;

}}

}}

i=0; /*Copiar los números de regreso*/ for(j=0;j<10;j++) /* al arreglo x[N] */ {

p=f[j]; while(p!=-1)

{x[i++]=node[p].info;p=node[p].next;

}}

printf("\n"); for(i=0;i<N;i++) printf("x[%d]=%d\n",i,x[i]); getchar();}

 

 

Los requisitos de espacio del ordenamiento de calculo de dirección son aproximadamente 2*n (utilizado mediante el arreglo node) más algunos nodos de encabezado y variables temporales. Observe que si los

Page 27: ORDENAMIENTO DE DATOS

datos originales se proporcionan en la forma de una lista ligada y no como un arreglo secuencia l, no es necesario conservar el arreglo x y la estructura vinculada node.

Para evaluar los requisitos de tiempo para el ordenamiento considere lo siguiente: si la distribución aproximada de los n elementos originales está uniform emnete distribuida por los m subarchivos y el valor de n/m es aproximadamente 1, el tiempo de ordenamiento es casi O(n),dado que la función asigna cada elemento a su propio archivo y se requiere poco trabajo adicional para colocar el elemento dent ro del subarchivo mismo. Por otra parte, si n/m es mucho más grande que 1, o si el archivo original no esta uniformemente distribuido por los m subarchivos, se requiere bastante trabajo para insertar un elemento en su propio suba