You are on page 1of 10

Ordenamiento por Shell (Shell Sort) Concepto: La ordenacin Shell debe el nombre a su inventor, D. L. Shell.

Se suele denominar tambin ordenacin por insercin con incrementos decrecientes. Se considera que el mtodo Shell es una mejora de los mtodos de insercin directa. Este mtodo tambin se conoce con el nombre de insercin con incrementos decrecientes. En el mtodo de ordenacin por insercin directa cada elemento se compara para su ubicacin correcta en el arreglo, con los elementos que se encuentran en la parte izquierda del mismo. Si el elemento a insertar es ms pequeo que el grupo de elementos que se encuentran a su izquierda, es necesario efectuar entonces varias comparaciones antes de su ubicacin. Shell propone que las comparaciones entre elementos se efecten con saltos de mayor tamao pero con incrementos decrecientes, as los elementos quedarn ordenados en el arreglo ms rpidamente. El Shell Sort es una generalizacin del ordenamiento por insercin, teniendo en cuenta dos observaciones: 1. El ordenamiento por insercin es eficiente si la entrada est "casi ordenada". 2. El ordenamiento por insercin es ineficiente, en general, porque mueve los valores slo una posicin cada vez. El algoritmo Shell Sort mejora el ordenamiento por insercin comparando elementos separados por un espacio de varias posiciones. Esto permite que un elemento haga "pasos ms grandes" hacia su posicin esperada. Los pasos mltiples sobre los datos se hacen con tamaos de espacio cada vez ms pequeos. El ltimo paso del Shell Sort es un simple ordenamiento por insercin, pero para entonces, ya est garantizado que los datos del vector estn casi ordenados.

Explicacin: En el algoritmo de insercin, cada elemento se compara con los elementos contiguos de su izquierda, uno tras otro. Si el elemento a insertar es el ms pequeo hay que realizar muchas comparaciones antes de colocarlo en su lugar definitivo. A diferencia del algoritmo de ordenacin por insercin, este algoritmo intercambia elementos distantes. Es por esto que puede deshacer ms de una inversin en cada intercambio, hecho que se aprovecha para ganar velocidad. El algoritmo de Shell modifica los saltos contiguos resultantes de las comparaciones por saltos de mayor tamao y con ello se consigue que la ordenacin sea ms rpida. Generalmente se toma como salto inicial n/2 (siendo n el nmero de elementos), luego se reduce el salto a la mitad en cada repeticin hasta que el salto es de tamao 1.

La velocidad del algoritmo depender de una secuencia de valores (llamados incrementos) con los cuales trabaja utilizndolos como distancias entre elementos a intercambiar. En algunas secuencias se pueden obtener ordenes de tiempo de ejecucin en el peor caso de O(n2), O(n^(3/2)) y O(n^(4/3)). Se considera la ordenacin de Shell como el algoritmo ms adecuado para ordenar entradas de datos moderadamente grandes (decenas de millares de elementos) ya que su velocidad, si bien no es la mejor de todos los algoritmos, es aceptable en la prctica y su implementacin (cdigo) es relativamente sencillo. Secuencia k-ordenada. Se dice que una secuencia A de n elementos est k-ordenada (siendo k un natural) si, para todo i de [0,n] se cumple que los elementos A[i + hk] estn ordenados, siendo h un entero y siempre que el ndice i+hk est en [0,n]. El algoritmo de ordenacin de Shell lo que hace en realidad es tomar una secuencia de incrementos h1, h2, ..., hp y en la etapa k-esima realizar una hk-ordenacin de los datos. La nica condicin que debe respetar la secuencia de incrementos es hp=1 de modo tal que en la ltima etapa se hace una 1-ordenacin (o sea una ordenacin normal). Dado que la ordenacin por insercin lo que hace es una 1-ordenacin, usara el mismo algoritmo para k-ordenar, pero comparando slo elementos k-distanciados. Ms detalladamente, para cada i de [k+1, n] intercambiara (si hay que hacerlo) A[i] con alguno de los elementos anteriores a i con distancia mltiplo de k (es decir, intercambiara A[i] con alguno de los elementos A[i-k], A[i-2k], ...). Una propiedad importante de implementar una k-ordenacin de este modo es que si k>p entonces realizar una p-ordenacin luego de una k-ordenacin conserva el k-orden. La ordenacin por insercin trabaja mucho ms rpido si la secuencia de datos est "casi ordenada". As, luego de efectuar varias k-ordenaciones, en la ltima etapa, la 1-ordenacin tiene un array "casi ordenado", por lo que el algoritmo se ejecuta ms rpidamente. Se puede decir entonces que la ordenacin de Shell, es en realidad una ordenacin por insercin pero a la cual se le pasa el array "casi ordenado". Esta "casi ordenacin" se efecta mediante hKordenaciones para algunos hK. La velocidad del algoritmo depender de esta secuencia de incrementos hK y una buena secuencia de incrementos constar de naturales primos relativos entre s. Secuencias de incrementos usadas comnmente La propuesta por Shell: n/2, n/4, ..., n/(2k), ..., 1. Ventajas: es fcil de calcular. Desventajas: no optimiza mucho la velocidad del algoritmo puesto que los incrementos tienen factores comunes (no son primos relativos). El tiempo de ejecucin promedio con esta secuencia de incrementos ser O(n2).

La propuesta por Hibbard: 2k-1, ..., 7, 3, 1; donde k se elige de modo tal que 2k-1 < n/2 y 2k+1-1 > n/2. Aunque no se ha podido demostrar formalmente (slo por medio de simulaciones), utilizar esta secuencia de incrementos hace que el algoritmo de Shell tenga un tiempo de ejecucin promedio O(n5/4). Una cota para el peor caso (que se puede demostrar utilizando la teora de nmeros y combinatoria avanzada) es O(n3/2). La propuesta por Sedgewick: 4k-32k+1, ..., 19, 5, 1; con la cual se pueden obtener tiempos de ejecucin O(n4/3) para el peor caso y O(n7/6) para el caso promedio. Ejemplo: ordenar una lista de elementos siguiendo paso a paso el mtodo de Shell. Obtener las secuencias parciales del vector al aplicar el mtodo Shell para ordenar en orden creciente la lista: Para el arreglo a = [6, 1, 5, 2, 3, 4, 0] El nmero de elementos que tiene la lista es 7, por lo que el salto inicial es 7/2 = 3. La siguiente tabla muestra el nmero de recorridos realizados en la lista con los saltos correspondientes.

Recorrido 1 2 3 4 5

Salto 3 3 3 1 1

Lista Ordenada 2,1,4,0,3,5,6 0,1,4,2,3,5,6 0,1,4,2,3,5,6 0,1,2,3,4,5,6 0,1,2,3,4,5,6

Intercambio (6,2), (5,4), (6,0) (2,0) Ninguno (4,2), (4,3) Ninguno

Algoritmo de ordenacin Shell Los pasos a seguir por el algoritmo para una lista de n elementos: 1. Se divide la lista original en n/2 grupos de dos, considerando un incremento o salto entre los elementos de n/2. 2. Se clasifica cada grupo por separado, comparando las parejas de elementos y si no estn ordenados se intercambian.

3. Se divide ahora la lista en la mitad de grupos (n/4), con un incremento o salto entre los elementos tambin mitad (n/4), y nuevamente se clasifica cada grupo por separado. 4. As sucesivamente, se sigue dividiendo la lista en la mitad de grupos que en el recorrido anterior con un incremento o salto decreciente en la mitad que el salto anterior y despus clasificando cada grupo por separado. 5. El algoritmo termina cuando se alcanza el tamao de salto 1. Por consiguiente, los recorridos por la lista estn condicionados por el bucle, intervalo n/2

mientras (intervalo > 0) hacer Para dividir la lista en grupos y clasificar cada grupo se anida este cdigo, desde i j (intervalo + 1) hasta n hacer

i - intervalo

mientras (j > 0) hacer k j + intervalo

si (a[j] <= a[k])entonces j 0

sino Intercambio (a[j], a[k]); j j - intervalo

fin_si fin_mientras fin_desde Se puede observar que se comparan pares de elementos indexados por j y k, (a[j],a[k]), separados por un salto, intervalo . As, si n = 8 el primer valor de intervalo = 4, y los ndices i = 5, j = 1, k = 6. Los siguiente valores que toman i = 6, j = 2, k = 7 y as hasta recorrer la lista. Para realizar un nuevo recorrido de la lista con la mitad de grupos, el intervalo se hace la mitad. intervalo intervalo / 2

Y as sucesivamente se repiten los recorridos por la lista, con el bucle: mientras intervalo > 0.

Codificacin del mtodo Shell Al codificar en C este mtodo de ordenacin es necesario tener en cuenta que el operador / realiza una divisin entera si los operandos son enteros y esto es importante al calcular el ancho del saltos entre pares de elementos: intervalo = n/2. En cuanto a los ndices, C toma como base el ndice 0, como consecuencia hay que desplazar una posicin a la izquierda las variables ndice respecto a lo expuesto en el algoritmo. void ordenacionShell(double a[], int n) { int intervalo, i, j, k; intervalo = n / 2; while (intervalo > 0) { for (i = intervalo; i < n; i++) { j = i - intervalo; while (j >= 0) { k = j + intervalo; if (a[j] <= a[k]) j = -1; /* as termina el bucle, par ordenado */ else { double temp; temp = a[j]; a[j] = a[k];

a[k] = temp; j -= intervalo; } } } intervalo = intervalo / 2; } }

Ejercicio: Teniendo el siguiente array {55, 36, 19, 24, 25, 50}

Salto=3: Primera iteracin: {24, 36, 19, 55, 25, 50} <-- Cambia el 55 y el 24. {24, 25, 19, 55, 36, 50} <-- Cambia el 36 y el 25. Salto=1: Primera iteracin: {24, 19, 25, 55, 36, 50} <-- Cambia el 25 y el 19. {19, 24, 25, 55, 36, 50} <-- Cambia el 24 y el 19. {19, 24, 25, 36, 55, 50} <-- Cambia el 55 y el 36. Segunda iteracin: {19, 24, 25, 36, 50, 55} <-- Cambia el 55 y el 50.

#include<stdio.h> #include<conio.h> void main(){ clrscr(); int Cantidad, opcion, i, j, k, Aux, intb, l; int Vector[100]; {printf("\n\n\tCuantos numeros seran introducidos: "); scanf("%d",&Cantidad); printf("\n"); for(i=1;i<=Cantidad;i++) {printf("\tVector[%d]=",i); scanf("%d",&Vector[i]); } intb = Cantidad / 2; while(intb>0) {for(i=intb+1;i<=Cantidad;i++) {j = i - intb; while(j>0) {k = j + intb; if(Vector[j]<Vector[k]) {j=0;} else {printf("\n\n\tCambiando... Vector[%d]=%d por Vector[%d]=%d\n",j,Vector[j],k,Vector[k]); Aux = Vector[j]; Vector[j] = Vector[k]; Vector[k] = Aux; for(l=1;l<=Cantidad;l++)

{printf("\t%d",Vector[l]);} } j = j - intb; } } intb = intb / 2; } printf("\n\n\t\tVECTOR ORDENADO\n"); for(i=1;i<=Cantidad;i++) {printf("\t%d",Vector[i]);} }getch();}

Conclusiones Este es un algoritmo eficaz, relativamente eficiente en la mayora de los casos, fcil de implementar, no consume memoria extra dinmicamente y se comporta bastante bien para unos datos de entrada de mediano tamao.

Bibliografa

- http://es.wikipedia.org/wiki/Ordenamiento_Shell - http://www.mcgraw-hill.es/bcv/guide/capitulo/8448198441.pdf - http://es.scribd.com/doc/1739233/Ordenamiento-en-C - http://www.dcc.uchile.cl/~bebustos/files/Bus99.pdf - http://html.rincondelvago.com/ordenacion-por-shell.html - http://www.monografias.com/trabajos/algordenam/algordenam.shtml - http://latecladeescape.com/algoritmos/1124-ordenacion-por-el-metodo-de-shell-shellsort - http://www.angelfire.com/wy2/est_info/shell.html

You might also like