1).Ordenamiento de burbuja El Ordenamiento de burbuja (Bubble Sort en inglés) es un sencillo algoritmo de ordenamiento. Funciona revisando cada elemento de la lista que va a ser ordenada con el siguiente, intercambiándolos de posición si están en el orden equivocado. Es necesario revisar varias veces toda la lista hasta que no se necesiten más intercambios, lo cual significa que la lista está ordenada. Este algoritmo obtiene su nombre de la forma con la que suben por la lista los elementos durante los intercambios, como si fueran pequeñas "burbujas". También es conocido como el método del intercambio directo. Dado que solo usa comparaciones para operar elementos, se lo considera un algoritmo de comparación, siendo el más sencillo de implementar. Descripción Una manera simple de expresar el ordenamiento de burbuja en pseudocódigo es la siguiente: Este algoritmo realiza el ordenamiento de una lista a den valores, en este caso de n términos numerados del 0al n-1, consta de dos bucles anidados uno con el índicei, que da un tamaño menor al recorrido de la burbuja en sentido inverso de 2 a n, y un segundo loop con el índice j, con un recorrido desde 0 hasta n-i, para cada iteración del primer bucle, que indica el lugar de la burbuja. La burbuja son dos términos de la lista seguidos, j yj+1, que se comparan, si el primero es menor que el segundo sus valores se intercambian. Esta comparación se repite en el centro de los dos bucles, dando lugar a la postre a una lista ordenada, puede verse que el número de repeticiones sola depende de n, y no del orden de los términos, esto es si pasamos al algoritmo una lista ya ordenada, realizara todas las comparaciones exactamente igual que para una lista no ordenada, esta es una característica de este algoritmo, luego verano una variante que evita este inconveniente. Para comprender el funcionamiento, veamos un ejemplo sencillo: Tenemos una lista de números que hay que ordenar: Podemos ver que la lista que tiene cinco términos, luego: El índice i hará un recorrido de 2 hasta n: Que en este caso será de 2 a 5. Para cada uno de los valores de i, j tomara sucesivamente los valores de 0 hasta n-i: Para cada valor de j, obtenido en ese orden, se compara el valor del índice j con el siguiente: Si el termino j es menor, en su caso podría se mayor, q u e e l t e r mino j+1, los valores se permutan, en caso contrario se continúa con la iteración. Para el caso del ejemplo, tenemos que: Para la primera iteración del primer bucle: y j tomara los valores de 0 hasta 3: Cuando j vale 0, se comparan , el 55 y el 86, dado que 55 < 86 no se permutan el orden. Ahora j vale 1 y se comparan el 86 y el 48 Como 86 > 48, se permutan, dando lugar a una nueva lista. Se repite el proceso hasta que j valga 3, dando lugar a una re lista super ordenada, podemos ver que el termino de mayor valor esta en el lugar más alto. Ahora i vale 3, y j hará un recorrido de 0 a 2. Primero j vale 0, se comparan , el 55 y el 48, como 55 > 48 se permutan dando lugar a la nueva lista. Para j = 1 se compara el 55 con el 16 y se cambian de orden. Para j = 2 se compara el 55 y el 82 y se dejan como están, finalizando el bucle con una lista mejor ordenada, puede verse que los dos valores más altos ya ocupan su lugar. No se ha realizado ninguna comparación con el termino cuarto, dado que ya se sabe que después del primer ciclo es el mayor de la lista. El algoritmo consiste en comparaciones sucesivas de dos términos consecutivos, ascendiendo de abajo a arriba en cada iteración, como la ascensión de las burbujas de aire en el agua, de ahí el nombre del procedimiento, en la primera iteración el recorrido ha sido completo, en el segundo se ha dejado él último termino, al tener ya el mayor de los valores, en los sucesivos sé ira dejando re realizar las ultimas comparaciones, como se puede ver. Ahora ya i vale 4 y j recor rerá los valores de 0 a 1. Cuando j vale 0, se comparan esto es el 48 y el 16 dado que 48 es mayor que 16 se permutan los valores, dando lugar a una lista algo más ordenada que la anterior, desde esta nueva ordenación, j pasa a valer 1, con lo que se comparan los términos el 48 y el 55 que quedan en el mismo orden. En este caso la burbuja ha ascendido menos que en los casos anteriores, y la lista esta ya ordenada, pero el algoritmo tendrá que completarse, realizando una ultima iteración. Hay que tener en cuenta que el bucle para realiza un número fijo de repeticiones y para finalizar tendrán que completarse, aun en el caso extremo, de que la lista estaría previamente ordenada. Por último i vale 5 y j solo puede vale 0, con lo que solo se realizara una comparación de el 16 y el 48, que ya están ordenados y se dejan igual. Los bucles finalizan y también el procedimiento, dejando la lista ordenada. Una variante que finaliza en caso de que la lista este ordenada, puede ser la siguiente, empleando un centinela ordenado, que detecta que no se ha modificado la lista en un recorrido de la burbuja, y que por tanto la lista ya esta ordenada, finalizando. 2). Ordenamiento por inserción El ordenamiento por inserción (insertion sort en inglés) es una manera muy natural de ordenar para un ser humano, y puede usarse fácilmente para ordenar un mazo de cartas numeradas en forma arbitraria. Requiere O(n²) operaciones para ordenar una lista de n elementos. Inicialmente se tiene un solo elemento, que obviamente es un conjunto ordenado. Después, cuando hay k elementos ordenados de menor a mayor, se toma el elemento k+1 y se compara con todos los elementos ya ordenados, deteniéndose cuando se encuentra un elemento menor (todos los elementos mayores han sido desplazados una posición a la derecha). En este punto se inserta el elemento k+1 debiendo desplazarse los demás elementos. Ejemplo de funcionamiento En el siguiente ejemplo, 32 debe ser insertado entre 26 y 47, y por lo tanto 47, 59 y 96 deben ser desplazados. k+1 11 26 47 59 96 32 11 26 47 59 96 11 26 32 47 59 96 En la implementación computacional, el elemento k+1 va comparándose de atrás para adelante, deteniéndose con el primer elemento menor. Simultáneamente se van haciendo los desplazamientos. 11 11 11 11 11 26 26 26 26 26 47 59 96 47 59 47 59 47 59 32 47 59 32 96 96 96 96 El algoritmo en pseudocódigo (con listas que empiezan por 0) debería ser como el siguiente: algoritmo insertSort( A : lista de elementos ordenables ) para i=1 hasta longitud(A) hacer index=A[i] j=i-1 mientras j>=0 y A[j]>index hacer A[j+1] = A[j] j = j - 1 fin mientras A[j+1] = index fin para fin algoritmo Aunque este algoritmo tiene un mejor orden de complejidad que el de burbuja, es muy ineficiente al compararlo con otros algoritmos comoquicksort. Sin embargo, para listas relativamente pequeñas el orden por inserción es una buena elección, no sólo porque puede ser más rápido para cantidades pequeñas de elementos sino particularmente debido a su facilidad de programación. Java public static void insertSort (int[] v) { for (int i=1; i<v.length; i++) { int aux = v[i]; int j; for (j=i-1; j>=0 && v[j]>aux; j--) v[j+1] = v[j]; v[j+1] = aux; } } 3).Ordenamiento Shell El ordenamiento Shell (Shell sort en inglés) es un algoritmo de ordenamiento. El método se denomina Shell en honor de su inventorDonald Shell. Su implementación original, requiere O(n2) comparaciones e intercambios en el peor caso. Un cambio menor presentado en el libro de V. Pratt produce una implementación con un rendimiento de O(nlog2 n) en el peor caso. Esto es mejor que las O(n2) comparaciones requeridas por algoritmos simples pero peor que el óptimo O(n log n). Aunque es fácil desarrollar un sentido intuitivo de cómo funciona este algoritmo, es muy difícil analizar su tiempo de ejecución. El Shell sort es una generalización del ordenamiento por inserción, teniendo en cuenta dos observaciones: 1. El ordenamiento por inserción es eficiente si la entrada está "casi ordenada". 2. El ordenamiento por inserción es ineficiente, en general, porque mueve los valores sólo una posición cada vez. El algoritmo Shell sort mejora el ordenamiento por inserción comparando elementos separados por un espacio de varias posiciones. Esto permite que un elemento haga "pasos más grandes" hacia su posición esperada. Los pasos múltiples sobre los datos se hacen con tamaños de espacio cada vez más pequeños. El último paso del Shell sort es un simple ordenamiento por inserción, pero para entonces, ya está garantizado que los datos del vector están casi ordenados. Ejemplo Considere un pequeño valor que está inicialmente almacenado en el final del vector. Usando un ordenamiento O(n2) como el ordenamiento de burbuja o el ordenamiento por inserción, tomará aproximadamente n comparaciones e intercambios para mover este valor hacia el otro extremo del vector. El Shell sort primero mueve los valores usando tamaños de espacio gigantes, de manera que un valor pequeño se moverá bastantes posiciones hacia su posición final, con sólo unas pocas comparaciones e intercambios. Uno puede visualizar el algoritmo Shell sort de la siguiente manera: coloque la lista en una tabla y ordene las columnas (usando unordenamiento por inserción). Repita este proceso, cada vez con un número menor de columnas más largas. Al final, la tabla tiene sólo una columna. Mientras que transformar la lista en una tabla hace más fácil visualizarlo, el algoritmo propiamente hace su ordenamiento en contexto (incrementando el índice por el tamaño de paso, esto es usando i += tamaño_de_paso en vez de i++). Por ejemplo, considere una lista de números como [ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ]. Si comenzamos con un tamaño de paso de 5, podríamos visualizar esto dividiendo la lista de números en una tabla con 5 columnas. Esto quedaría así: 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 Entonces ordenamos cada columna, lo que nos da 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 Cuando lo leemos de nuevo como una única lista de números, obtenemos [ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]. Aquí, el 10 que estaba en el extremo final, se ha movido hasta el extremo inicial. Esta lista es entonces de nuevo ordenada usando un ordenamiento con un espacio de 3 posiciones, y después un ordenamiento con un espacio de 1 posición (ordenamiento por inserción simple). El Shell sort lleva este nombre en honor a su inventor, Donald Shell, que lo publicó en 1959. Algunos libros de texto y referencias antiguas le llaman ordenación "Shell-Metzner" por Marlene Metzner Norton, pero según Metzner, "No tengo nada que ver con el algoritmo de ordenamiento, y mi nombre nunca debe adjuntarse a éste." [1] [editar]Secuencia de espacios La secuencia de espacios es una parte integral del algoritmo Shell sort. Cualquier secuencia incremental funcionaría siempre que el último elemento sea 1. El algoritmo comienza realizando un ordenamiento por inserción con espacio, siendo el espacio el primer número en la secuencia de espacios. Continua para realizar un ordenamiento por inserción con espacio para cada número en la secuencia, hasta que termina con un espacio de 1. Cuando el espacio es 1, el ordenamiento por inserción con espacio es simplemente un ordenamiento por inserción ordinario, garantizando que la lista final estará ordenada. La secuencia de espacios que fue originalmente sugerida por Donald Shell debía comenzar con N / 2 y dividir por la mitad el número hasta alcanzar 1. Aunque esta secuencia proporciona mejoras de rendimiento significativas sobre los algoritmos cuadráticos como el ordenamiento por inserción, se puede cambiar ligeramente para disminuir más el tiempo necesario medio y el del peor caso. El libro de texto de Weiss demuestra que esta secuencia permite un ordenamiento O(n2) del peor caso, si los datos están inicialmente en el vector como (pequeño_1, grande_1, pequeño_2, grande_2, ...) - es decir, la mitad alta de los números están situados, de forma ordenada, en las posiciones con índice par y la mitad baja de los números están situados de la misma manera en las posiciones con índice impar. Quizás la propiedad más crucial del Shell sort es que los elementos permanecen kordenados incluso mientras el espacio disminuye. Se dice que un vector dividido en k subvectores esta k-ordenado si cada uno de esos subvectores esta ordenado en caso de considerarlo aislado. Por ejemplo, si una lista fue 5-ordenada y después 3-ordenada, la lista está ahora no sólo 3-ordenada, sino tanto 5-ordenada como 3-ordenada. Si esto no fuera cierto, el algoritmo desharía el trabajo que había hecho en iteraciones previas, y no conseguiría un tiempo de ejecución tan bajo. Dependiendo de la elección de la secuencia de espacios, Shell sort tiene un tiempo de ejecución en el peor caso de O(n2) (usando los incrementos de Shell que comienzan con 1/2 O(n3 / 2) (usando los incrementos de Hibbard de 2k − 1), O(n4 / 3) (usando los incrementos de Sedgewick de 9(4i) − 9(2i) + 1, o 4i + 1 + 3(2i) + 1), o O(nlog2n), y posiblemente mejores tiempos de ejecución no del tamaño del vector y se dividen por 2 cada vez), comprobados. La existencia de una implementación O(nlogn) en el peor caso del Shell sort permanece como una pregunta por resolver. [editar]Implementaciones El Shell sort se usa comúnmente en lenguajes de programación; esto es una implementación del algoritmo en C/C++ para ordenar un vectorde enteros. La secuencia de incrementos usada en este ejemplo de código da un tiempo de ejecución O(n2) en el peor caso. Java public static void shellSort(int[] a) { for ( int increment = a.length / 2; increment > 0; increment = (increment == 2 ? 1 : (int) Math.round(increment / 2.2))) { for (int i = increment; i < a.length; i++) { for (int j = i; j >= increment && a[j - increment] > a[j]; j -= increment) { int temp = a[j]; a[j] = a[j - increment]; a[j - increment] = temp; } } } } 4). Quicksort El ordenamiento rápido (quicksort en inglés) es un algoritmo basado en la técnica de divide y vencerás, que permite, en promedio, ordenar n elementos en un tiempo proporcional a n log n. Descripción del algoritmo El algoritmo consta de los siguientes pasos: Elegir un elemento de la lista de elementos a ordenar, al que llamaremos pivote. Resituar los demás elementos de la lista a cada lado del pivote, de manera que a un lado queden todos los menores que él, y al otro los mayores. Los elementos iguales al pivote pueden ser colocados tanto a su derecha como a su izquierda, dependiendo de la implementación deseada. En este momento, el pivote ocupa exactamente el lugar que le corresponderá en la lista ordenada. La lista queda separada en dos sublistas, una formada por los elementos a la izquierda del pivote, y otra por los elementos a su derecha. Repetir este proceso de forma recursiva para cada sublista mientras éstas contengan más de un elemento. Una vez terminado este proceso todos los elementos estarán ordenados. Como se puede suponer, la eficiencia del algoritmo depende de la posición en la que termine el pivote elegido. En el mejor caso, el pivote termina en el centro de la lista, dividiéndola en dos sublistas de igual tamaño. En este caso, el orden de complejidad del algoritmo es O(n·log n). En el peor caso, el pivote termina en un extremo de la lista. El orden de complejidad del algoritmo es entonces de O(n²). El peor caso dependerá de la implementación del algoritmo, aunque habitualmente ocurre en listas que se encuentran ordenadas, o casi ordenadas. Pero principalmente depende del pivote, si por ejemplo el algoritmo implementado toma como pivote siempre el primer elemento del array, y el array que le pasamos está ordenado, siempre va a generar a su izquierda un array vacío, lo que es ineficiente. En el caso promedio, el orden es O(n·log n). No es extraño, pues, que la mayoría de optimizaciones que se aplican al algoritmo se centren en la elección del pivote. [editar]Demostración Podríamos probar el orden de ejecución en el mejor caso de la siguiente manera: Vamos a suponer que el número total de elementos a ordenar es potencia de dos, es decir, n = 2k. de aquí podemos ver que k = log2(n), donde k es el número de divisiones que realizará el algoritmo. En la primera fase del algoritmo habrán n comparaciones, en la segunda fase el algoritmo creará dos sublistas aproximadamente de tamaño n/2. El número total de comparaciones de estas dos sublistas es: 2(n/2) = n. En la tercera fase el algoritmo procesará 4 sublistas más, por tanto el número total de comparaciones en esta fase es 4(n/4) = n. En conclusión, el número total de comparaciones que hace el algoritmo es: n + n + n + ..... + n = kn, donde k = log2(n), por tanto el tiempo de ejecución del algoritmo en el mejor caso es O(n.log2n) [editar]Optimización del algoritmo Cabe destacar que de usarse en su versión recursiva las siguientes optimizaciones y sus desventajas no se ven vistas en el tiempo de ejecución del mismo manteniéndose, así el tiempo de ejecución planteado en un principio. [editar]Técnicas de elección del pivote El algoritmo básico del metodo Quicksort consiste en tomar cualquier elemento de la lista al cual denominaremos como pivote, dependiendo de la partición en que se elija, el algoritmo será más o menos eficiente. Tomar un elemento cualquiera como pivote tiene la ventaja de no requerir ningún cálculo adicional, lo cual lo hace bastante rápido. Sin embargo, esta elección «a ciegas» siempre provoca que el algoritmo tenga un orden de O(n²) para ciertas permutaciones de los elementos en la lista. Otra opción puede ser recorrer la lista para saber de antemano qué elemento ocupará la posición central de la lista, para elegirlo como pivote. Esto puede hacerse en O(n) y asegura que hasta en el peor de los casos, el algoritmo sea O(n·log n). No obstante, el cálculo adicional rebaja bastante la eficiencia del algoritmo en el caso promedio. La opción a medio camino es tomar tres elementos de la lista - por ejemplo, el primero, el segundo, y el último - y compararlos, eligiendo el valor del medio como pivote. [editar]Técnicas de reposicionamiento Una idea preliminar para ubicar el pivote en su posición final sería contar la cantidad de elementos menores que él, y colocarlo un lugar más arriba, moviendo luego todos esos elementos menores que él a su izquierda, para que pueda aplicarse la recursividad. Existe, no obstante, un procedimiento mucho más efectivo. Se utilizan dos índices: i, al que llamaremos índice izquierdo, y j, al que llamaremos índice derecho. El algoritmo es el siguiente: Recorrer la lista simultáneamente con i y j: por la izquierda con i (desde el primer elemento), y por la derecha con j (desde el último elemento). Cuando lista[i] sea mayor que el pivote y lista[j] sea menor, se intercambian los elementos en esas posiciones. Repetir esto hasta que se crucen los índices. El punto en que se cruzan los índices es la posición adecuada para colocar el pivote, porque sabemos que a un lado los elementos son todos menores y al otro son todos mayores (o habrían sido intercambiados). [editar]Transición a otro algoritmo Como se comentó antes, el algoritmo quicksort ofrece un orden de ejecución O(n²) para ciertas permutaciones "críticas" de los elementos de la lista, que siempre surgen cuando se elige el pivote «a ciegas». La permutación concreta depende del pivote elegido, pero suele corresponder a secuencias ordenadas. Se tiene que la probabilidad de encontrarse con una de estas secuencias es inversamente proporcional a su tamaño. Los últimos pases de quicksort son numerosos y ordenan cantidades pequeña de elementos. Un porcentaje medianamente alto de ellos estarán dispuestos de una manera similar al peor caso del algoritmo, volviendo a éste ineficiente. Una solución a este problema consiste en ordenar las secuencias pequeñas usando otro algoritmo. Habitualmente se aplica el algoritmo de inserción para secuencias de tamaño menores de 8-15 elementos. Pese a que en secuencias largas de elementos la probabilidad de hallarse con una configuración de elementos "crítica" es muy baja, esto no evita que sigan apareciendo (a veces, de manera intencionada). El algoritmo introsort es una extensión del algoritmo quicksort que resuelve este problema utilizando heapsort en vez de quicksort cuando el número de recursiones excede al esperado. Parámetros: Se debe llamar a la función Quicksort desde donde quiera ejecutarse Ésta llamará a colocar pivote para encontrar el valor del mismo Se ejecutará el algoritmo Quicksort de forma recursiva a ambos lados del pivote int colocar(int *v, int b, int t) { int i; int pivote, valor_pivote; int temp; pivote = b; valor_pivote = v[pivote]; for (i=b+1; i<=t; i++){ if (v[i] < valor_pivote){ pivote++; temp=v[i]; v[i]=v[pivote]; v[pivote]=temp; } } temp=v[b]; v[b]=v[pivote]; v[pivote]=temp; return pivote; } void Quicksort(int* v, int b, int t) { int pivote; if(b < t){ pivote=colocar(v, b, t); Quicksort(v, b, pivote-1); Quicksort(v, pivote+1, t); } } Nota: Los tres parámetros de la llamada inicial a Quicksort serán array[0], 0, numero_elementos -1, es decir, si es un array de 6 elementos array[0], 0, 5 [editar]Ejemplo En el siguiente ejemplo se marcan el pivote y los índices i y j con las letras p, i y j respectivamente. Comenzamos con la lista completa. El elemento pivote será el 4: 5 - 3 - 7 - 6 - 2 - 1 - 4 p Comparamos con el 5 por la izquierda y el 1 por la derecha. 5 - 3 - 7 - 6 - 2 - 1 - 4 i j p 5 es mayor que 4 y 1 es menor. Intercambiamos: 1 - 3 - 7 - 6 - 2 - 5 - 4 i j p Avanzamos por la izquierda y la derecha: 1 - 3 - 7 - 6 - 2 - 5 - 4 i j p 3 es menor que 4: avanzamos por la izquierda. 2 es menor que 4: nos mantenemos ahí. 1 - 3 - 7 - 6 - 2 - 5 - 4 i j p 7 es mayor que 4 y 2 es menor: intercambiamos. 1 - 3 - 2 - 6 - 7 - 5 - 4 i j p Avanzamos por ambos lados: 1 - 3 - 2 - 6 - 7 - 5 - 4 iyj p En este momento termina el ciclo principal, porque los índices se cruzaron. Ahora intercambiamos lista[i] con lista[sup] (pasos 16-18): 1 - 3 - 2 - 4 - 7 - 5 - 6 p Aplicamos recursivamente a la sublista de la izquierda (índices 0 - 2). Tenemos lo siguiente: 1 - 3 - 2 1 es menor que 2: avanzamos por la izquierda. 3 es mayor: avanzamos por la derecha. Como se intercambiaron los índices termina el ciclo. Se intercambia lista[i] con lista[sup]: 1 - 2 - 3 El mismo procedimiento se aplicará a la otra sublista. Al finalizar y unir todas las sublistas queda la lista inicial ordenada en forma ascendente. 1 - 2 - 3 - 4 - 5 - 6 - 7 [editar]Implementaciones El algoritmo de ordenamiento rápido (Quicksort) en: Pseudocódigo function quicksort(array) var list, less, greater if length(array) ≤ 1 return array seleccionar y eliminar un valor pivote pivot en el array for each x in array if x < pivot then añadir x a less else añadir x a greater return concadenar(quicksort(less), pivot, quicksort(greater)) Java //Recibe un vector de enteros y el índice del primer y último elemento válido del mismo void ordenarQuicksort(int[] vector, int primero, int ultimo){ int i=primero, j=ultimo; int pivote=vector[(primero + ultimo) / 2]; int auxiliar; do{ while(vector[i]<pivote) i++; while(vector[j]>pivote) j--; if (i<=j){ auxiliar=vector[j]; vector[j]=vector[i]; vector[i]=auxiliar; i++; j--; } } while (i<=j); if(primero<j) ordenarQuicksort(vector,primero, j); if(ultimo>i) ordenarQuicksort(vector,i, ultimo); } 5).Ordenamiento por selección El ordenamiento por selección (Selection Sort en inglés) es un algoritmo de ordenamiento que requiere O(n2)operaciones para ordenar una lista de n elementos. Su funcionamiento es el siguiente: Buscar el mínimo elemento de la lista Intercambiarlo con el primero Buscar el mínimo en el resto de la lista Intercambiarlo con el segundo Y en general: Buscar el mínimo elemento entre una posición i y el final de la lista Intercambiar el mínimo con el elemento de la posición i De esta manera se puede escribir el siguiente pseudocódigo para ordenar una lista de n elementos indexados desde el 1: para i=1 hasta n-1 minimo = i; para j=i+1 hasta n si lista[j] < lista[minimo] entonces minimo = j /* (!) */ fin si fin para intercambiar(lista[i], lista[minimo]) fin para Este algoritmo mejora ligeramente el algoritmo de la burbuja. En el caso de tener que ordenar un vector de enteros, esta mejora no es muy sustancial, pero cuando hay que ordenar un vector de estructuras más complejas, la operación intercambiar() sería más costosa en este caso. Este algoritmo realiza muchas menos operaciones intercambiar() que el de la burbuja, por lo que lo mejora en algo. Si la línea comentada con (!) se sustituyera por intercambiar(lista[i], lista[j]) tendríamos una versión del algoritmo de la burbuja (naturalmente eliminando el orden intercambiar del final). Otra desventaja de este algoritmo respecto a otros como el de burbuja o de inserción directa es que no mejora su rendimiento cuando los datos ya están ordenados o parcialmente ordenados. Así como, por ejemplo, en el caso de la ordenación de burbuja se requeriría una única pasada para detectar que el vector ya está ordenado y finalizar, en la ordenación por selección se realizarían el mismo número de pasadas independientemente de si los datos están ordenados o no. [editar]Implementaciones Java void selecccion(int[] a) { for (int i = 0; i < a.length - 1; i++) { int min = i; for (int j = i + 1; j < a.length; j++) { if (a[j] < a[min]) { min = j; } } if (i != min) { int aux= a[i]; a[i] = a[min]; a[min] = aux; } } } 6). Ordenamiento por mezcla El algoritmo de ordenamiento por mezcla (merge sort en inglés) es un algoritmo de ordenamiento externo estable basado en la técnicadivide y vencerás. Es de complejidad O(n log n). Descripción Fue desarrollado en 1945 por John Von Neumann. Conceptualmente, el ordenamiento por mezcla funciona de la siguiente manera: 1. Si la longitud de la lista es 0 ó 1, entonces ya está ordenada. En otro caso: 2. Dividir la lista desordenada en dos sublistas de aproximadamente la mitad del tamaño. 3. Ordenar cada sublista recursivamente aplicando el ordenamiento por mezcla. 4. Mezclar las dos sublistas en una sola lista ordenada. El ordenamiento por mezcla incorpora dos ideas principales para mejorar su tiempo de ejecución: 1. Una lista pequeña necesitará menos pasos para ordenarse que una lista grande. 2. Se necesitan menos pasos para construir una lista ordenada a partir de dos listas también ordenadas, que a partir de dos listas desordenadas. Por ejemplo, sólo será necesario entrelazar cada lista una vez que están ordenadas. A continuación se describe el algoritmo en pseudocódigo (se advierte de que no se incluyen casos especiales para vectores vacíos, etc.; una implementación en un lenguaje de programación real debería tener en cuenta estos detalles): function mergesort(array A[x..y]) begin if (x-y > 1)): array A1 := mergesort(A[x..(int( x+y / 2))]) array A2 := mergesort(A[int(1+(x+y / 2))..y]) return merge(A1, A2) else: return A end function merge(array A1[0..n1], array A2[0..n2]) begin integer p1 := 0 integer p2 := 0 array R[0..(n1 + n2 + 2)]//suponiendo que n1 y n2 son las posiciones //del array y no el length de este mismo, de otro modo seria (n1 + n2) while (p1 <= n1 or p2 <= n2): if (p1 <= n1 and A1[p1] <= A2[p2]): R[p1 + p2] := A1[p1] p1 := p1 + 1 else if (p2 <= n2 and A1[p1] > A2[p2]): R[p1 + p2] := A2[p2] p2 := p2 + 1 return R end [editar]Implementaciones Java public class MergeSort{ private int A[]; public int[] OrdenaMerge(int[] L) { int n = L.length; if (n > int int int 1){ m = (int) (Math.ceil(n/2.0)); [] L1 = new int[m]; [] L2 = new int[n-m]; for (int i = 0; i < m; i++){ L1[i] = L[i]; } for (int i = m; i < n; i++){ L2[i-m] = L[i]; } L = merge(OrdenaMerge(L1), OrdenaMerge(L2)); } return L; } public int[] eliminar(int [] l){ int [] L = new int[l.length-1]; for(int i = 1; i < l.length; i++){ L[i-1] = l[i]; } return L; } public int[] merge(int[] L1, int[] L2) { int[] L = new int[L1.length+L2.length]; int i = 0; while ((L1.length != 0) && (L2.length != 0)) { if (L1[0] < L2[0]){ L[i++] = L1[0]; L1 = eliminar(L1); if (L1.length == 0){ while (L2.length != 0) { L[i++] = L2[0]; L2 = eliminar(L2); } } } else{ L[i++] = L2[0]; L2 = eliminar(L2); if (L2.length == 0) { while (L1.length != 0) { L[i++] = L1[0]; L1 = eliminar(L1); } } } } return L; } public void generarNumeros(){ Random ran = new Random(); int x; for(int i = 0; i < A.length; i++){ x = (int)(ran.nextDouble()*10000); A[i] = x; } } public void imprimir(){ for(int i = 0; i < A.length; i++){ System.out.println(A[i]); } } public int[] getA(){ return A; } public void setA(int []A){ this.A = A; } }