Está en la página 1de 16

ORDENACIN POR BURBUJA

El mtodo de ordenacin por burbuja es el ms conocido y popular entre estudiantes y aprendices de programacin, por su facilidad de comprender y programar; por el contrario, es el menos eficiente y por ello, normalmente, se aprende su tcnica pero no suele utilizarse. La tcnica utilizada se denomina ordenacin por burbuja u ordenacin por hundimiento debido a que los valores ms pequeos burbujean gradualmente (suben) hacia la cima o parte superior del array de modo similar a como suben las burbujas en el agua, mientras que los valores mayores se hunden en la parte inferior del array. La tcnica consiste en hacer varias pasadas a travs del array. En cada pasada, se comparan parejas sucesivas de elementos. Si una pareja est en orden creciente (o los valores son idnticos), se dejan los valores como estn. Si una pareja est en orden decreciente, sus valores se intercambian en el array. Algoritmo de la burbuja En el caso de un array (lista) con n elementos, la ordenacin por burbuja requiere hasta n-1 pasadas. Por cada pasada se comparan elementos adyacentes y se intercambian sus valores cuando el primer elemento es mayor que el segundo elemento. Al final de cada pasada, el elemento mayor ha burbujeado hasta la cima de la sublista actual. Por ejemplo, despus que la pasada 0 est completa, la cola de la lista a[n-1] est ordenada y el frente de la lista permanece desordenado. Las etapas del algoritmo son : En la pasada 1 se comparan elementos adyacentes
(a[0],a[1]),(a[1],a[2]),(a[2],a[3]),...(a[n-2],a[n-1])

Se realizan n-1 comparaciones, por cada pareja (a[i],a[i+1]) se intercambian los valores si a[i+1] < a[i]. Al final de la pasada, el elemento mayor de la lista est situado en a[n-1] . En la pasada 2 se realizan las mismas comparaciones e intercambios, terminando con el elemento de segundo mayor valor en a[n-2] . El proceso termina con la pasada n-1, en la que el elemento ms pequeo se almacena en a[0] . El algoritmo tiene una mejora inmediata, el proceso de ordenacin puede terminar en la pasada n-1, o bien antes, si en un una pasada no se produce intercambio alguno entre elementos del array es porque ya est ordenado, entonces no es necesario mas pasadas. El ejemplo siguiente ilustra el funcionamiento del algoritmo de la burbuja con un array de 5 elementos (A = 50, 20, 40, 80, 30) donde se introduce una variable interruptor para detectar si se ha producido intercambio en la pasada.
Pasada 1

50

20 40 80

30

Intercambio 50 y 20

20

50 40 80

30

Intercambio 50 y 40

20

40 50 80

30

50 y 80 ordenados

20

40 50 80

30

Intercambio 80 y 30

20
Pasada 2

40 50 30

80

Elemento mayor es 80 interruptor = TRUE

20

40 50 30

80

20 y 40 ordenados

20

40 50 30

80

40 y 50 ordenados

20

40 50 30 80

Se intercambian 50 y 30

20 40
Pasada 3

30

50

80

50 y 80 elementos mayores y ordenados interruptor = TRUE

20

40 30 50

80

20 y 40 ordenados

20
Pasada 4

30 40 50

80

Se intercambian 40 y 30 interruptor = TRUE

20

30 40 50

80

20 y 30 ordenados

20

30 40 50

80

Lista ordenada interruptor = FALSE

En consecuencia, el algoritmo de ordenacin de burbuja mejorado contempla dos bucles anidados: el bucle externo controla la cantidad de pasadas (al principio de la primera pasada todava no se ha producido ningn intercambio por tanto la variable interruptor se pone a valor falso(false); el bucle interno controla cada pasada individualmente y cuando se produce un intercambio, cambia el valor de interruptor a verdadero (true).

El algoritmo terminar, bien cuando se termine la ltima pasada (n-1) o bien cuando el valor del interruptor sea falso, es decir no se haya hecho ningn intercambio. Codificacin del algoritmo de la burbuja El mtodo ordBurbuja() implementa el algoritmo de ordenacin de la burbuja, tiene como argumento el array que se va a ordenar crecientemente. El intercambio de dos elementos se realiza llamando al mtodo void intercambiar(long []a, int i, int j). Se ha elegido entero largo (long) como tipo de los elementos del array.
public static void ordBurbuja (long a[]) { boolean interruptor = true; int pasada, j; int n = a.length; // bucle externo controla la cantidad de pasadas for (pasada = 0; pasada < n-1 && interruptor; pasada++) { interruptor = false; for (j = 0; j < n-pasada-1; j++) if (a[j] > a[j+1]) { // elementos desordenados, se intercambian interruptor = true; intercambiar(a, j, j+1); } } }

Una mejora del algoritmo anterior consiste en utilizar, en lugar de una variable bandera interruptor, una variable indiceIntercambio que se inicie a 0 al principio de cada pasada y se establezca al ndice del ltimo intercambio, de modo que cuando al terminar la pasada el valor de indiceIntercambio siga siendo 0 implicar que no se ha producido ningn intercambio (o bien, que el intercambio ha sido con el primer elemento) , y, por consiguiente, la lista estar ordenada. En caso de no ser 0, el valor de indiceIntercambio representa el ndice del array a partir del cual los elementos estn ordenados. La codificacin de esta alternativa:
public static void ordBurbuja2 (long a[]) { int i, j; int indiceIntercambio; int n = a.length; i = n-1; while (i > 0) { indiceIntercambio = 0; // explorar la sublista a[0] a a[i] for (j = 0; j < i; j++) if (a[j+1] < a[j]) { indiceIntercambio = j; intercambiar(a, j, j+1); } i = indiceIntercambio; } }

Anlisis del algoritmo de la burbuja Cul es la eficiencia del algoritmo de ordenacin de la burbuja ? Depender de la versin utilizada. En la versin ms simple se hacen n-1 pasadas y n-1 comparaciones en cada pasada. Por consiguiente, el nmero de comparaciones es (n-1) * (n-1) = n2 - 2n + 1, es decir la complejidad es 0(n2). Si se tienen en cuenta las versiones mejoradas, haciendo uso de las variables interruptor o indiceIntercambio, entonces se tendr una eficiencia diferente a cada algoritmo. En el mejor de los casos, la ordenacin de burbuja hace una sola pasada en el caso de una lista que ya est ordenada en orden ascendente y por tanto su complejidad es 0(n). En el caso peor se requieren (n-i-1) comparaciones y (n-i-1) intercambios. La n( n 1) ordenacin completa requiere comparaciones y un nmero similar de 2 intercambios. La complejidad para el caso peor es 0(n2) comparaciones y 0(n2) intercambios. De cualquier forma, el anlisis del caso general es complicado dado que alguna de las pasadas pueden no realizarse. Se podra sealar que el nmero medio de pasadas k es 0(n) y el nmero total de comparaciones es 0(n2). En el mejor de los casos, la ordenacin por burbuja puede terminar en menos de n-1 pasadas pero requiere, normalmente, muchos ms intercambios que la ordenacin por seleccin y su prestacin media es mucho ms lenta, sobre todo cuando los arrays a ordenar son grandes.
A tener en cuenta Los algoritmos de ordenacin interna: intercambio, seleccin, insercin y burbuja son fciles de entender y de codificar, sin embargo poco eficientes y no recomendables para ordenar listas de muchos elementos. La complejidad de todos ellos es cuadrtica, 0(n2).

EJERCICIO 1 Con el fin de medir el tiempo en milisegundos que emplea en ordenar un computador utilizando los mtodos: intercambio, seleccin, insercin y burbuja, se desea escribir un programa que genere un array de 1000 elementos obtenidos al azar, se ordene aplicando cada uno de los algoritmos y mida el tiempo empleado por el computador. La clase MetodosBasicosOrdenacion dispone de los mtodos de ordenacin que han sido implementados, todos para arrays de tipo int. Al ser mtodos static no se crea un objeto de la clase, directamente se llama al mtodo con el cualificador de la clase. El mtodo main() define el array, asigna elementos aleatorios llamando al mtodo Math.random(), llama a cada mtodo de ordenacin. Para determinar el tiempo de ordenacin se utiliza System.currentTimeMillis()(devuelve tiempo en milisegundos) antes y despus de cada llamada al mtodo de ordenacin, la diferencia es el tiempo transcurrido.
import ordenainterna.MetodosBasicosOrdenacion; import java.io.*; public class OrdenaInterna {

public static void main(String args[]) { final int M = 10000; int [] v = new int [M]; int [] c = new int [M]; long k1, k2; entrada(v); System.arraycopy(v,0,c,0,v.length); k1 = System.currentTimeMillis(); OrdenacBasica.ordIntercambio(c); k2 = System.currentTimeMillis(); System.out.println("\nTiempo ordenacin por intercambio: " + (k2 - k1)); System.arraycopy(v,0,c,0,v.length); k1 = System.currentTimeMillis(); OrdenacBasica.ordInsercion(c); k2 = System.currentTimeMillis(); System.out.println("\nTiempo ordenacin por insercin: " + (k2 - k1)); System.arraycopy(v,0,c,0,v.length); k1 = System.currentTimeMillis(); OrdenacBasica.ordBurbuja(c); k2 = System.currentTimeMillis(); System.out.println("\nTiempo ordenacin por burbuja: " + (k2 - k1)); System.arraycopy(v,0,c,0,v.length); k1 = System.currentTimeMillis(); OrdenacBasica.ordBurbuja2(c); k2 = System.currentTimeMillis(); System.out.println("\nTiempo ordenacin por burbuja(2): " + (k2 - k1)); System.arraycopy(v,0,c,0,v.length); k1 = System.currentTimeMillis(); OrdenacBasica.ordSeleccion(c); k2 = System.currentTimeMillis(); System.out.println("\nTiempo ordenacin por seleccion: " + (k2 - k1));

} static void entrada(int [] w) { int SUP =9999; for (int i = 0; i< w.length; i++) w[i] = (int)(Math.random() * SUP + 1); } }

MTODOS DE ORDENACIN BINSORT Y RADIXSORT


Estos mtodos de ordenacin utilizan urnas para depositar en ellas los registros en el proceso de ordenacin. En cada recorrido de la lista a ordenar se deposita en una urnai aquellos registros cuya clave tienen una cierta correspondencia con el ndice i . Mtodo de ordenacin Binsort (ordenacin por urnas) Este mtodo, tambin llamado clasificacin por urnas, se propone conseguir funciones tiempo de ejecucin de complejidad menor de O(n log n) para ordenar una lista de n elementos, siempre que se conozca alguna relacin del campo clave de los elementos respecto de las urnas. Dado un array v[]de registros, se desea ordenar respecto un campo clave de tipo entero, adems se sabe que los valores de las claves se encuentran en el rango de 1 a n, sin claves duplicadas y siendo n el nmero de elementos. En estas circunstancias ideales es posible ubicar los registros ordenados en un array auxiliar t[] mediante este nico bucle:
for i = 1 to n do t[v[i].clave]= v[i];

Sencillamente, determina la posicin del registro que le corresponde segn el valor del campo clave. El bucle lleva un tiempo de ejecucin de complejidad lineal O(n). Esta ordenacin tan sencilla que se ha expuesto es un caso particular del mtodo de ordenacin por urnas (binsort). Este mtodo utiliza urnas, cada urna contiene todos los registros con una misma clave. El proceso consiste en examinar cada registro r a clasificar y situarle en la urna i, coincidiendo i con el valor del campo clave de r. En la mayora de los caso en que se utilice el algoritmo ser necesario guardar ms de un registro en una misma urna por tener claves repetidas. Entonces estas urnas hay que concatenarlas en el orden de menor ndice de urna a mayor, as quedar el array en orden creciente respecto al campo clave. En la Figura 6.3 se muestra un vector de m urnas. Las urnas estn representadas por listas enlazadas.
Urnas 1 2 R1 R2 R3 R1 R2 R3 R1 R2 R3

Rm

Rm

Rm

Figura 6.3 Estructura formada por m urnas

Algoritmo de ordenacin Binsort. El algoritmo se aplica sobre listas de registros con un campo clave cuyo rango de valores es relativamente pequeo respecto al nmero de registros. Normalmente el campo clave es de tipo entero, en el rango 1 .. m. Son necesarias m urnas por ello se declara un vector de m urnas. Las urnas se representan mediante listas enlazadas, cada elemento de la lista contiene un registro cuyo campo clave se corresponde con el ndice de la urna en la que se encuentra, normalmente la clave ser igual al ndice de la urna. As en la urna 1 se sitan los registros cuyo campo clave es 1, en la urna 2 los registros cuyo campo clave es 2, y as sucesivamente en la urna i se sitan los registros cuyo campo clave es igual a i . La primera accin del algoritmo consiste en distribuir los registros en las diversas urnas. Una vez realizada la distribucin, es necesario concatenar las listas enlazadas para formar un nica lista con los registros en orden creciente; por ltimo, se recorre la lista asignando cada nodo al vector, y de esa manera el vector de registros queda en orden respecto al campo clave. La Figura 6.4 se muestra cmo realizar la concatenacin.
R1 R2 R3 Rm R1 R2 R3 Rm ... R1 R2 R3 Rm

Figura 6.4 Concatenacin de urnas representadas por listas enlazadas.

Los pasos que sigue el algoritmo expresado en seudocdigo para un vector de n registros:
OrdenacionBinsort(vector, n) inicio CrearUrnas(Urnas); {Distribucin de registros en sus correspondientes urnas} desde j = 1 hasta n hacer AadirEnUrna(Urnas[vector[j].clave], vector[j]); fin_desde {Concatena las listas que representan a las urnas desde Urnai hasta Urnam} i = 1; {bsqueda de primera urna no vaca} mientras EsVacia(Urnas[i]) hacer i = i+1 fin_mientras desde j = i+l a m hacer EnlazarUrna(Urnas[i], Urnas[j]); fin_desde {recorre las lista(urnas) resultado de la concatenacin} j = 1; dir = <frente Urnas[i]>;

mientras dir <> nulo hacer vector[j] = <registro apuntado por dir>; j = j+i; dir = Sgte(dir) fin_mientras fin

Mtodo de ordenacin RadixSort (ordenacin por residuos) Este mtodo de ordenacin es un caso particular del algoritmo de clasificacin por urnas. La idea intuitiva de mtodo de ordenacin por residuos se encuentra en los pasos que se siguen a la hora de ordenar, de forma manual, un conjunto de fichas; consiste en formar diversos montones de fichas, cada uno caracterizado por tener sus componentes un mismo dgito (letra, si es ordenacin alfabtica) en la misma posicin, inicialmente primera posicin que son las unidades; estos montones se recogen en orden ascendente, desde el montn del dgito 0 al montn del dgito 9. Entonces las fichas estn ordenadas respecto a las unidades. A continuacin se vuelve a distribuir las fichas en montones, segn el dgito que est en la segunda posicin (decenas). El proceso de distribuir las fichas por montones y posterior acumulacin en orden se repite tantas veces como nmero de dgitos tiene la ficha de mayor valor. Se desea ordenar la siguiente lista de fichas, aplicando los pasos del algoritmo RadixSort; las fichas estn identificadas por un campo entero de tres dgitos:
345, 721, 425, 572, 836, 467, 672, 194, 365, 236, 891, 746, 431, 834, 247, 529, 216, 389

Atendiendo al dgito de menor peso (unidades) las fichas se distribuyen en montones del 0 al 9:
431 891 721 1 672 572 2 834 194 4 365 425 345 5 216 746 236 836 6 247 467 7 389 529 9

Recogiendo los montones en orden ascendente la lista de fichas es la siguiente:


721, 891, 431, 572, 672, 194, 834, 345, 425, 365, 836, 236, 746, 216, 467, 247, 529, 389

Esta lista ya est ordenada respecto al dgito de menor peso, respecto a las unidades. Pues bien, ahora de nuevo se distribuye la secuencia de fichas en montones respecto al segundo dgito:
529 425 721 2 236 836 834 431 3 247 746 345 4

216 1

467 365 6

672 572 7

389 8

194 891 9

Recogiendo los montones en orden ascendente, la lista de fichas es la siguiente:

216, 721, 425, 529, 431, 834, 836, 236, 345, 746, 247, 365, 467, 572, 672, 389, 891, 194

En este momento las fichas ya estn ordenadas respecto a los dos ltimos dgitos, es decir respecto a las decenas. Por ltimo, se distribuye las fichas en montones respecto al tercer dgito:
247 236 216 2 389 365 345 3 467 431 425 4 572 529 5 746 721 7 891 836 834 8

194 1

672 6

Recogiendo de nuevo los montones en orden ascendente, la lista de fichas ya est ordenada:
194, 216, 236, 247, 345, 365, 389, 425, 431, 467, 529, 572, 672, 721, 746, 834, 836, 891

Algoritmo de ordenacin RadixSort. La idea clave de la ordenacin RadixSort es clasificar por urnas, primero respecto al dgito de menor peso, (unidades); despus respecto al dgito del siguiente peso (decenas), y as sucesivamente se contina hasta alcanzar el dgito ms significativo. Una vez terminada la clasificacin respecto al dgito mas significativo la lista est ordenada. En cada paso hay que unir las urnas en orden ascendente, desde la urna 0 a la urna 9; consiste, simplemente, en enlazar el final de una urna con el frente de la siguiente. Al igual que en el mtodo de BinSort, las urnas se representan mediante un array de listas enlazadas. Se ha de disponer de tantas urnas como dgitos, 10 urnas, numeradas de 0 a 9. Si la clave respecto a la que se ordena es alfabtica, habr tantas urnas como letras distintas, desde la urna que representa a la letra a hasta la z. El algoritmo que se escribe, en primer lugar determina el nmero mximo de dgitos que puede tener una clave. Un bucle de tantas iteraciones como el mximo de dgitos, realiza las acciones de distribuir por urnas los registros, concatenar... La distribucin por urnas exige obtener el dgito del campo clave que se encuentra en la posicin definida por el bucle externo, dicho dgito ser el ndice de la urna.
OrdenacionRadixsort(vector, n) inicio { clculo el nmero mximo de dgitos: ndig } ndig = 0; temp = maximaClave; mientras (temp > 0) hacer ndig = ndig+1 temp = temp / 10; fin_mientras peso =1 { permite obtener los dgitos de menor a mayor peso} desde i = 1 hasta ndig hacer CrearUrnas(Urnas); desde j = 1 hasta n hacer d = (vector[j] / peso) modulo 10; AadirEnUma(Urnas[d], vector[j]); fin_desde { bsqueda de primera urna no vaca: j } desde r = j+1 hasta M hace { M: nmero de urnas }

EnlazarUma(Urnas[r], Urnas[j]); fin_desde {Se recorre la lsta-urna resultante de la concatenacin} r = 1; dir = frente(Urna[j]); mientras dir <> nulo hacer vecto[r] = dir.registro; r = r+1; dir = siguiente(dir) fin_mientras peso = peso * 10; fin_desde fin_ordenacion

Mtodos de ordenacin bsicos


package ordenainterna; public class MetodosBasicosOrdenacion { public static void intercambiar(int []a, int i, int j) { int aux = a[i]; a[i] = a[j]; a[j]= aux ; } public static void intercambiar(long []a, int i, int j) { long aux = a[i]; a[i] = a[j]; a[j]= aux ; } public static void intercambiar(double[]a, int i, int j) { double aux = a[i]; a[i] = a[j]; a[j]= aux ; } public static void ordIntercambio (int a[]) { int i, j; for (i = 0 ; i < a.length-1; i++) // sita mnimo de a[i+1]...a[n-1] en a[i] for (j = i+1 ; j < a.length; j++) if (a[i] > a[j]) { intercambiar(a, i, j); } } public static void ordInsercion (int [] a) { int i, j; int aux; for (i = 1; i < a.length; i++) { /* indice j es para explorar la sublista a[i-1]..a[0] buscando la posicion correcta del elemento destino*/ j = i; aux = a[i]; // se localiza el punto de insercin explorando hacia abajo while (j > 0 && aux < a[j-1]) { // desplazar elementos hacia arriba para hacer espacio a[j] = a[j-1]; j--; } a[j] = aux; } }

public static void ordBurbuja (int a[]) { boolean interruptor = true; int pasada, j; int n = a.length; // bucle externo controla la cantidad de pasadas for (pasada = 0; pasada < n-1 && interruptor; pasada++) { interruptor = false; for (j = 0; j < n-pasada-1; j++) if (a[j] > a[j+1]) { // elementos desordenados, se intercambian interruptor = true; intercambiar(a, j, j+1); } } } public static void ordBurbuja2 (int a[]) { int i, j; int indiceIntercambio; int n = a.length; i = n-1; while (i > 0) { indiceIntercambio = 0; // explorar la sublista a[0] a a[i] for (j = 0; j < i; j++) if (a[j+1] < a[j]) { indiceIntercambio = j; intercambiar(a, j, j+1); } i = indiceIntercambio; }

public static void ordSeleccion (int a[]) { int indiceMenor, i, j, n; n = a.length; // ordenar a[0]..a[n-2] y a[n-1] en cada pasada for (i = 0; i < n-1; i++) { // comienzo de la exploracin en ndice i indiceMenor = i; // j explora la sublista a[i+1]..a[n-1] for (j = i+1; j < n; j++) if (a[j] < a[indiceMenor]) indiceMenor = j; // sita el elemento mas pequeo en a[i] if (i != indiceMenor) intercambiar(a, i, indiceMenor); }

} }

Mtodos de ordenacin Shell


public static void ordenacionShell(double a[]) { int intervalo, i, j, k; int n= a.length; 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; // par de elementos ordenado else { intercambiar(a, j, j+1); j -= intervalo; } } } intervalo = intervalo / 2; } }

Mtodo de ordenacin quicksort


public static void quicksort(double a[]) { quicksort(a, 0, a.length-1); } private static void quicksort(double a[], int primero, int ultimo) { int i, j, central; double pivote; central = (primero + ultimo)/2; pivote = a[central]; i = primero; j = ultimo; do { while (a[i] < pivote) i++; while (a[j] > pivote) j--; if (i <= j) { intercambiar(a, i, j); i++; j--; } }while (i <= j); if (primero < j) quicksort(a, primero, j); // mismo proceso con sublista izqda if (i < ultimo) quicksort(a, i, ultimo); // mismo proceso con sublista drcha

Captulo 6, Ordenacin de un vector de nmeros racionales


class Racional implements Comparador { int numerador, denominador; public boolean igualQue(Object op2) { Racional n2 = (Racional) op2; return ((double)numerador / (double)denominador) == ((double)n2. numerador / (double)n2. denominador );

public boolean menorQue(Object op2) { Racional n2 = (Racional) op2; return } ((double)numerador / (double)denominador) < ((double)n2. numerador / (double)n2. denominador );

public boolean menorIgualQue(Object op2) { Racional n2 = (Racional) op2; return ((double)numerador / (double)denominador) <= ((double)n2. numerador / (double)n2. denominador ); } public boolean mayorQue(Object op2) { Racional n2 = (Racional) op2; return ((double)numerador / (double)denominador) > ((double)n2. numerador / (double)n2. denominador ); } public boolean mayorIgualQue(Object op2) { Racional n2 = (Racional) op2; return ((double)numerador / (double)denominador) >= ((double)n2. numerador / (double)n2. denominador ); } } private static void intercambiar (Vector v, int i, int j) { Object aux = v.elementAt(i); v.setElementAt(v.elementAt(j), i); v.setElementAt(aux, j); } public static void ordVector (Vector v) { boolean interruptor = true; int pasada, j; int n = v.size(); // bucle externo controla la cantidad de pasadas for (pasada = 0; pasada < n-1 && interruptor; pasada++) { interruptor = false; for (j = 0; j < n-pasada-1; j++) { Racional r; r = (Racional)v.elementAt(j); if (r.mayorQue(v.elementAt(j+1))) { // elementos desordenados, se intercambian interruptor = true; intercambiar(v, j, j+1); } } } }

Bsqueda binaria
public int busquedaBin(int a[],int clave) { int central, bajo, alto; int valorCentral; bajo = 0; alto = a.length - 1; while (bajo <= alto) { central = (bajo + alto)/2; // ndice de elemento central valorCentral = a[central]; // valor del ndice central if (clave == valorCentral) return central; // encontrado, devuelve posicin else if (clave < valorCentral) alto = central -1; // ir a sublista inferior else bajo = central + 1; // ir a sublista superior } return -1; //elemento no encontrado }

También podría gustarte