Professional Documents
Culture Documents
(DAA-2009)
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Asumamos que nos dan una sucesin de n-elementos X[1], X[2], ... X[N], y que cada X[i], tiene
asociada una clave denotada por clave(X[i]). Se supone que existe una relacin de orden total sobre
las claves, esto significa que se cumple una de las siguientes posibilidades, ya sea:
Existen mtodos directos de ordenacin, tales como por insercin que se refiere en insertar un
elemento dado en el lugar que le corresponde de una parte ya ordenada del array, por ejemplo,
InsertionSort, InsertionBinaria. Otra forma es a travs de la seleccin que consiste en seleccionar el
menor elemento de una parte desordenada del array y colocarlo en la posicin del primer elemento
no ordenado e intercambio que se refiere en comparar pares de elementos adyacentes e
intercambiarlos si estn desordenados, dentro de esta estrategia estn, por ejemplo, mtodo de la
burbuja o intercambio directo y el (ShakerSort) que es una variante del anterior. Existen otros
mtodos ms avanzados de clasificacin u ordenacin, ellos son: Insercin por incremento
decreciente (ShellSort), ordenacin por Heap (HeapSort) y clasificacin rpida o por particin
(QuickSort).
Una importante propiedad de algunos algoritmos de ordenacin es la estabilidad y se refiere a que el
orden relativo de los elementos con claves iguales permanece inalterado en el proceso de
clasificacin, es decir, no intercambia elementos con claves iguales.
Algunos algoritmos de ordenamiento agrupados segn estabilidad tomando en cuenta la
complejidad computacional.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Notar que despus de realizado el recorrido del array los datos estn ordenados.
INSERTION-SORT(A)
1 for j 2 to length[A]
2
do key A[j]
3
Insert A[j] into the sorted sequence A[1 .. j - 1].
4
i j - 1
5
while i > 0 and A[i] > key
6
do A[i + 1] A[i]
7
i i - 1
8
A[i + 1] key
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
INSERTION-SORT(A)
1 for j 2 to length[A]
2
do key A[j]
3
Insert A[j] into the sorted sequence A[1 .. j - 1]
4
i j - 1
5
while i > 0 and A[i] > key
6
do A[i + 1] A[i]
7
i i - 1
8
A[i + 1] key
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Notar que se necesitan 4 pasadas para que el array este finalmente ordenado.
BUBBLESORT(A)
1 for i 1 to length[A]
2
do for j length[A] downto i + 1
3
do if A[j] < A[j - 1]
4
then exchange A[j] A[j - 1]
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
En un primer paso se ordenan por insercin directa los elementos que estn separados 4 posiciones,
es as como deben ordenarse las claves de las posiciones 1, 5 y 9, con claves 8, 3 y 22
respectivamente; las posiciones 2 y 6 con claves 14 y 23; las posiciones 3 y 7 con claves 5 y 17; y
las posiciones 4 y 8 con claves 9 y 13, esta forma se conoce como clasificacin 4, de la misma
manera se acta con clasificacin 2 y 1 respectivamente.
/**
* Shellsort, usando una secuencia sugerida por Gonnet.
* a un array de claves int.
**/
shellsort(int[] a) {
for (int gap = a.length / 2; gap > 0;
gap = (gap == 2) ? 1 : (int) (gap / 2.2)) {
for (int i = gap; i < a.length; i++) {
int tmp = a[i];
int j = i;
for (; (j >= gap) && (tmp < a[j - gap]); j -= gap) {
a[j] = a[j - gap];
}
a[j] = tmp;
}
Tal como se adelantaba la operacin fundamental de este algoritmo es mezclar las dos listas
ordenadas. La idea bsica es tomar dos arrays de entrada A y B es orden, y la salida se entrega en el
array C. Vamos a considerar tres contadores, Actr, Bctr, y Cctr, para mostrar un ejemplo de cmo
trabaja. En todo caso, digamos que el ms pequeo de los A[Actr] y B[Bctr] es copiado en la
siguiente entrada en C (es decir, C[Cctr]), y el contador apropiado avanza. Cuando la lista de
entrada ha sido analizada, el resto de la otra lista es copiada a C.
Ejemplo: Veamos como trabaja para el array A: 1, 13, 24, 26, 2, 15, 27, 38.
MergeSort(A, p, r)
if p<r then
q= (p+r)/2
MergeSort(A, p, q)
MergeSort(A, q+1, r)
Merge(A, p, q, r)
4 for i 1 to n1
5
do L[i] A[p + i - 1]
6 for j 1 to n2
7
do R[j] A[q + j]
8 L[n1 + 1]
9 R[n2 + 1]
10 i 1
11 j 1
12 for k p to r
13
do if L[i] R[j]
14
then A[k] L[i]
15
i i + 1
16
else A[k] R[j]
17
j j + 1
Para ordenar una sucesin de entrada A=(A(1), A(2)...A(n)) se debe llamar a MergeSort(A, 1,
length[A]), donde length[A] = n.
Ejecucin de MergeSort() recursivo, visualizando las diversas particiones que se realizan.
Ahora se muestra una traza en trmino de las llamadas al procedimiento MergeSort y Merge, para el
array A: 55, 22, 44, 66, 11, 33, 22, 66.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Una muestra de ordenacin por particin para un arrays de 9 elementos, se puede ver a
continuacin, en donde estn los detalles para la obtencin de la primera particin. Dada la entrada
de 7-elementos
Ejemplo.
Dada la lista o array 5 - 3 - 7 - 6 - 2 - 1 - 4. Comenzamos con la lista completa. El elemento divisor
o pivote es 4:
5-3-7-6-2-1-4
Comparamos con el 5 por la izquierda y el 1 por la derecha.
5-3-7-6-2-1-4
5 es mayor que cuatro y 1 es menor. Intercambiamos:
1-3-7-6-2-5-4
Avanzamos por la izquierda y la derecha:
1-3-7-6-2-5-4
3 es menor que 4: avanzamos por la izquierda. 2 es menor que 4: nos mantenemos ah.
1-3-7-6-2-5-4
7 es mayor que 4 y 2 es menor: intercambiamos.
1-3-2-6-7-5-4
Avanzamos por ambos lados:
1-3-2-6-7-5-4
En este momento termina el ciclo principal, porque los ndices se cruzaron. Ahora intercambiamos
con el pivote, quedando
1-3-2-4-7-5-6
Aplicando en forma recursiva el proceso pero a la sub-lista 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
1-2-3
Para resumir la segunda sub-lista, se tiene
7-5-6
5-7-6
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
5-6-7
Para cada nueva sub-lista se retorna sin hacer cambios (se cruzan los ndices).
Finalmente, al retornar de la primera llamada se tiene el arreglo ordenado:
1 - 2 - 3 - 4 - 5 - 6 7.
Sea el array A[p..r], donde p es el primer ndice y r el ltimo del array.
QUICKSORT(A, p, r)
1 if p < r
2 then q PARTITION(A, p, r)
3 QUICKSORT(A, p, q - 1)
4 QUICKSORT(A, q + 1, r)
Ejemplo:
En este caso, se pretende mostrar como se logra la primera particin del array, para luego realizarlo
en forma recursiva. Consideremos el array
el pivote se indicar con un asterisco(*) y con un crculo(O) los elementos que se deben
intercambiar para obtener las sucesivas particiones.
Veamos en detalle como se obtiene la primera particin.
se comienza inicializando los ndices i y j a la primera y ltima posicin del array (elementos 3 y
22). A continuacin, se comienza a incrementar el ndice del inicio(i) hasta que se encuentre un
elemento que no sea menor que el pivote, lo que se consigue al llegar al segundo elemento(14).
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
una vez localizado un elemento mayor o igual, se ir el ndice de final(j) decrementando hasta
encontrar un elemento que sea menor(o igual) que el pivote(5). Se intercambian estos dos elementos
y se avanzan ambos ndices (se incrementa i y se decrementa j).
Ahora se sigue con el mismo proceso, es decir, se comienza a incrementar i hasta localizar un
elemento no menor que el pivote y despus se decrementa j hasta localizar uno no mayor, se
intercambian y se avanzan los dos ndices.
Se contina el proceso realizando todos los intercambios necesarios hasta que ambos ndices se
crucen.
En este momento tenemos en la parte inferior del array los elementos menores o igual al pivote y en
la otra los mayores.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
A continuacin, se procede de la misma manera con cada una de las particiones, en la primera el
pivote ser el 5 y en la segunda ser 23. Esto da lugar a nuevas particiones hasta que al final todas
las particiones quedan de tamao 1 con lo que el array queda ordenado. En efecto,
17
66
43
21
91
14
18
Ejemplo
Con este ejemplo para A = (55, 22, 44, 66, 11, 33, 22, 66) deseo mostrar la relevancia de las
llamadas al procedimiento recursivo QuickSort() con su procedimiento Partition().
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
11
22
33 33
44
55
66 77
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
38
25
46
17
60
22
33
76
72
12
95
85
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
38
25
46
17
60
22
33
76
72
12
95
85
X [1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
12
25
46
17
60
22
33
76
72
38
95
85
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
X [1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
12
25
38
17
60
22
33
76
72
46
95
85
J
X [1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
12
25
33
17
60
22
38
76
72
46
95
85
X [1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
12
25
33
17
38
22
60
76
72
46
95
85
Las posiciones 7 y 12 marcan la 2 seccin. Bajo el principio antes sealado podemos continuar
escogiendo el pivote y realizando lo mismo de antes pero para estas secciones en forma
independiente despus de realizada las particiones respectivas.
1.
Seccin
[1]
[2]
[3]
[4]
[5]
[1]
[2]
[3]
12
25
33
17
22
25
33
17
22
33
17
25
22
25
17
22
17
25
33
2.
[4]
22
33
Seccin
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
[1]
[2]
[3]
[4]
[5]
[6]
[1]
[2]
[3]
[4]
[5]
[6]
60
76
72
46
95
85
46
76
72
60
95
85
46
60
72
76
95
72
76
95
85
85
12
25
33
37
48
57
86
92
7-comparaciones
12
25
33
37
48
57
86
92
12
25
33
37
48
57
86
92
12
25
33
37
48
57
86
92
12
25
33
37
48
57
86
92
12
25
33
37
48
57
86
92
12
25
33
37
48
57
12
25
33
37
48
57
6-comparaciones
5-comparaciones
4-comparaciones
3-comparaciones
2-comparaciones
86
92
1-comparacin
86
92
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Se puede verificar que son necesarias 28-comparaciones, en general se necesitan [ (n -1) + (n -2) +
(n -3) + ....+ 1] - comparaciones, para una entrada de n-elementos, lo que hace que sea proporcional
a n2. Existen en todo caso un gran nmero de estrategias con el fin de mejorar la eleccin del pivote.
Anlisis Informal:
PARTITION realiza (n) comparaciones (donde n = r - p + 1).
Caso peor: para cuando el array esta ordenado, dada una particin no balanceada:
T(n) = (n) + T(n-1) + T(1), lo que implica T(n) = (n2).
Caso mejor: particiones ideales, cada vez:
T(n) = (n) + 2T(n/2), lo que implica T(n) = (n lgn).
Caso promedio: probablemente (nlgn), ya que an con malas particiones (digamos 99-1),
se tiene T(n) = (n) + T( 99n /100 ) + T( n/100) , lo que implica T(n) = (n lg n).
Una primera sugerencia sera hacer uso de un nmero aleatorio para elegir el elemento de divisin,
pero el costo relacionado con la generacin de nmeros seudo-aleatorios podra ser prohibitivo, otra
estrategia muy exitosa es la estrategia de las medianas, que consiste en escoger el pivote de entre 3
elementos, datos[inf], datos[mitad] y datos[sup], especficamente el algoritmo selecciona la
mediana de estos tres elementos con base en el valor de la clave, permitiendo as asegurar que el
elemento de divisin no est ubicado en ninguno de los extremos del array. Existen otras variante,
como la mediana de cinco que trabaja en forma similar. Ahora desde el punto de vista performance (
o rendimiento) es posible usar el algoritmo de Insercin (InsertionSort) en los subarray que se
obtienen, pero cuando son suficientemente pequeos.
Ejemplo:
Se muestra a continuacin una demo de quick sort con median-of-three partitioning. Su tarea si
desea emprenderla es generar otras formas de particionar y compararlas en tiempo, n de
comparaciones o de llamadas a los procedimientos si son recursivos.
class ArrayIns
{
private long[] elArray;
// referencia al array elArray
private int nElems;
// numero de elementos
//-------------------------------------------------------------public ArrayIns(int max)
// constructor
{
elArray = new long[max];
// crea el array
nElems = 0;
// no hay elementos
}
//-------------------------------------------------------------public void insert(long valor)
// put elemento al array
{
elArray[nElems] = valor;
// insertarlo
nElems++;
// incrementa el tamao
}
//-------------------------------------------------------------public void display()
// displays el contenido del array
{
System.out.print("A=");
for(int j=0; j<nElems; j++)
// para todos los elementos,
System.out.print(elArray[j] + " "); // display
System.out.println("");
}
//-------------------------------------------------------------public void quickSort()
{
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
recQuickSort(0, nElems-1);
}
//-------------------------------------------------------------public void recQuickSort(int izq, int der)
{
int tam = der-izq+1;
if(tam <= 3)
// orden manual si el tam es pequeo
manualSort(izq, der);
else
// quicksort si es grande
{
long mediana = medianDe3(izq, der);
int particion = particionIt(izq, der, mediana);
recQuickSort(izq, particion-1);
recQuickSort(particion+1, der);
}
} // end recQuickSort()
//-------------------------------------------------------------public long medianDe3(int izq, int der)
{
int centro = (izq+der)/2;
// ordena izq & centro
if( elArray[izq] > elArray[centro] )
swap(izq, centro);
// ordena izq & der
if( elArray[izq] > elArray[der] )
swap(izq, der);
// ordena centro & der
if( elArray[centro] > elArray[der] )
swap(centro, der);
swap(centro, der-1);
// put el pivot a la der
return elArray[der-1];
// return valor mediana
} // end medianDe3()
//-------------------------------------------------------------public void swap(int dex1, int dex2) // swap 2 elementos
{
long temp = elArray[dex1];
// A en temp
elArray[dex1] = elArray[dex2];
// B en A
elArray[dex2] = temp;
// temp en B
} // end swap(
//-------------------------------------------------------------public int particionIt(int izq, int der, long pivote)
{
int izqPtr = izq;
// der del primer elemento
int derPtr = der - 1;
// izq de pivote
while(true)
{
while( elArray[++izqPtr] < pivote ) // hallar el ms grande
;
//
(nop)
while( elArray[--derPtr] > pivote ) // hallar el ms pequeo
;
//
(nop)
if(izqPtr >= derPtr)
// si los punteros se cruzan,
break;
//
particion no se realiza
else
// no se cruzan
swap(izqPtr, derPtr); // swap los elementos
} // end while(true)
swap(izqPtr, der-1);
// restaura el pivote
return izqPtr;
// return lugar del pivote
} // end partitionIt()
//-------------------------------------------------------------_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Otra aplicacin interesante del algoritmo de ordenamiento QuickSort es el clculo del k-simo
mayor elemento de una lista de datos, pues permite adems de ordenar un array, calcular en forma
eficaz el k-simo elemento mayor del mismo. Observar que calcular la mediana consiste en calcular
el k-simo elemento mayor, con k = n/2. El k-simo mayor elemento de un vector es aquel elemento
que, tras ordenar el vector, ocupa la posicin nmero k.
Por ejemplo, para averiguar el sexto mayor (3- mayor) elemento del vector:
v = (2, 3, 6, 8, 3, 4, 1, 5, 3, 5, 6, 1) lo ordenamos:
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
int i = p;
int j = q+1;
int k = 0;
while ( i <= q && j <= r )
if (A[i] < A[j])
B[k++] = A[i++];
else B[k++] = A[j++];
while ( i <= q )
B[k++] = A[i++];
while ( j <= r )
B[k++] = A[j++];
for (i=0; i < k; i++)
A[p+i] = B[i];
(j)
0
1
2
3
:
:
:
:
tam
tam
tam
tam
=
=
=
=
1000; break;
2000; break;
5000; break;
10000; break;
}
}
Este otro programa usa las herramientas y mtodos de la librera Collection de Java para ordenar, en
donde la librera Java utiliza una variante de QuickSort
import java.util.*;
public class CollectionsSortDemo
{
public static void main(String args[])
{
String feld[] =
{ "Regina","Angela","Michaela","Maria","Josepha",
"Amalia","Vera","Valentina","Daniela","Saida", "Linda","Elisa" };
List l = Arrays.asList(feld);
Collections.sort(l);
System.out.println(l);
}
}
Este otro programa ordena datos de diferente ndole a travs de una Interface propia que
implementa el mtodo menorQue(), en la clase Algoritmos.java ( la que se debe encontrar en el
directorio en donde se ejecute la aplicacin Ejemplo_Ordenable.java
public class Algoritmos {
public static void ordenar(Ordenable a[ ]) {
Ordenable temp;
int este;
for (int i=0; i<a.length-1; i++) {
este = i;
for (int j=i+1; j<a.length; j++)
if (a[j].menorQue(a[este])) este = j;
temp=a[este];
a[este]=a[i];
a[i]=temp;
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
}
import java.util.*;
public class Ejemplo_Ordenable {
public static void main(String args[]) {
Pais[]paises={new Pais("Brasil"),new Pais("Argentina"),new Pais("Chile")};
Entero[] numeros={new Entero(3),new Entero(4), new Entero(1)};
Algoritmos.ordenar(paises);
Algoritmos.ordenar(numeros);
for (int i=0; i<paises.length; i++)
System.out.println(paises[i]);
for (int i=0; i<numeros.length; i++)
System.out.println(numeros[i]);
}
El orden en Java
Recordar que la Interface Comparable del paquete java.lang sirve entre otras cosas para
determinar el orden natural de los objetos.
/**************** Comparable.java *****************************
public interface Comparable
{
public int compareTo(Comparable a);
}
Desde la versin JDK 1.2 es la Interface Comparable lista para ser usada en diversas clases, tales
como String, Character, Double, etc. Sin embrago, existen otra tambin muy til, llamada Interface
Comparator .
/**************** Comparator.java *****************************
public interface Comparator
{
public int compare(Object element1, Object element2);
public boolean equals(Object o);
}
class Persona
{
private String apellido;
private String nombre;
private int edad;
//----------------------------------------------------------public Persona(String apell, String nom, int e)
{
// constructor
apellido = apell;
nombre = nom;
edad = e;
}
//----------------------------------------------------------public void displayPersona()
{
System.out.print("
Apellido : " + apellido);
System.out.print(", Nombre : " + nombre);
System.out.println(", Edad : " + edad);
}
//----------------------------------------------------------public String getApellido()
// obtener el apellido
{ return apellido; }
} // end class Persona
class ArrayConObj
{
private Persona[] a;
// refa al array a
private int nElems;
// numero de datos
//-------------------------------------------------------------public ArrayConObj(int max)
// constructor
{
a = new Persona[max];
// crea el array
nElems = 0;
// no existe por ahora
}
//-------------------------------------------------------------// put persona en el array
public void insert(String apell, String nom, int e)
{
a[nElems] = new Persona(apell, nom, e);
nElems++;
// incrementa el tamao
}
//-------------------------------------------------------------public void display()
// displays el contenido del array
{
for(int j=0; j<nElems; j++)
// para todos,
a[j].displayPersona();
// los display
}
//-------------------------------------------------------------public void insertionSort()
{
int in, out;
for(out=1; out<nElems; out++)
{
Persona temp = a[out];
in = out;
while(in>0 &&
a[in-1].getApellido().compareTo(temp.getApellido())>0)
{
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
}
}
a[in] = a[in-1];
--in;
}
a[in] = temp;
} // end for
// end insertionSort()
class OrdenandoObjetos
{
public static void main(String[] args)
{
int maxTam = 100;
ArrayConObj arr;
arr = new ArrayConObj(maxTam);
arr.insert("Evans", "Patty", 24);
arr.insert("Lopez", "Manuel", 59);
arr.insert("Salgado", "Laura", 37);
arr.insert("Smith", "Pablo", 37);
arr.insert("Yaez", "Tomas", 43);
arr.insert("Hashinomas", "Sato", 21);
arr.insert("Salco", "Brand", 29);
arr.insert("Velasquez", "Jose", 72);
arr.insert("Vega", "Manuel", 22);
arr.insert("Cresler", "Lucinda", 18);
System.out.println("Antes de Ordenar:");
arr.display();
arr.insertionSort();
System.out.println("Despues de Ordenar:");
arr.display();
} // end main()
// end class OrdenandoObjetos
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Este es otro ejemplo, el cual usa mtodo generics que usa wildcards para ordenar una lista en
orden ascendente. Bsicamente, todos los elementos en la lista deben ser implementados por la
interfaceComparable. http://java.sun.com/developer/technicalArticles/J2SE/generics/
publicstatic<TextendsComparable<?superT>>voidsort(List<T>list){
Objecta[]=list.toArray();
Arrays.sort(a);
ListIterator<T>i=list.listIterator();
for(intj=0;j<a.length;j++){
i.index();
i.set((T)a[j]);
}
}
http://www.dafi.upv.es/examenes/ad3_f97.pdf
Orden mediante Heap (Heapsort)
Dado un array A de n-elementos, la estrategia puede ser recursiva o iterativa, en cualquier caso este
mtodo se basa en la estructura de datos Heap. Recordemos que un Heap es un rbol binario
completo con informacin perteneciente a un conjunto ordenado. Los Heap tienen la caracterstica
de que cada nodo padre tiene un valor mayor que el de todos sus nodos hijos.
Un rbol cumple la condicin de Heap si satisface dicha condicin y adems es un rbol binario
completo. Un rbol binario es completo cuando todos los niveles estn llenos (ledos de izquierda a
derecha), con las excepcin del ltimo que puede quedar exento de dicho cumplimiento.
sta es la nica restriccin en los Heap. Ello implica que el mayor elemento (o el menor,
dependiendo de la relacin de orden escogida) est siempre en el nodo raz. Debido a esto, los heap
se utilizan para implementar colas de prioridad, por la razn de que en una cola siempre se consulta
el elemento de mayor valor, y esto conlleva la ventaja de que en los Heap dicho elemento est en la
raz. Otra ventaja que poseen los Heap es que su implementacin usando arrays es muy eficaz, por
la sencillez de su codificacin y liberacin de memoria, ya que no hace falta utilizar punteros. No
slo existen Heap ordenados con el elemento de la raz mayor que el de sus hijos, sino tambin que
la raz sea menor que sus progenitores. Todo depende de la ordenacin con la que nos interese
programar el Heap. La eficiencia de las operaciones en los Heap es crucial en diversos algoritmos
de recorrido de grafos y de ordenamiento HeapSort.
En un array A que representa un heap es un objeto con dos atributos: length[A], que es el n de
elementos en el array, y heap-size[A], que es el n de elementos en el heap almacenado dentro del
array A. En esta figura se muestra un max_heap, visto como un Heap (a) y como un array (b).
MAX-HEAPIFY(A, i)
1 l LEFT(i)
2 r RIGHT(i)
3 if l heap-size[A] and A[l] > A[i]
4 then largest l
5 else largest i
6 if r heap-size[A] and A[r] > A[largest]
7 then largest r
8 if largest i
9 then exchange A[i] A[largest]
10 MAX-HEAPIFY(A, largest)
La figura anterior muestra la accin de MAX-HEAPIFY(A, 2), donde heap-size[A] = 10. (a) La
configuracin inicial con A[2], en donde i = 2 viola la propiedad de max-heap ya que no es ms
grande que sus hijos. Luego en (b) se restaura la max-heap property para el nodo 2 intercambiendo
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
A[2] con A[4], la que vuelve a generar un problema, ahora con el nodo 4. Las llamadas recursivas a
MAXHEAPIFY(A, 4) con i = 4. Intercambia A[4] con A[9], se muestra en (c), nodo 4 ya restaurado.
Existe en todo caso toda una metodologa para transformar un rbol binario completo en un Heap.
BUILD-MAX-HEAP(A)
1 heap-size[A] length[A]
2 for i length[A]/2 downto 1
3 do MAX-HEAPIFY(A, i)
El algoritmo HeapSort parte usando Build-Heap para construir un heap sobre la entrada de datos
dada en A[1 .. n], donde n = length[A]. La figura siguiente muestra un ejemplo de la operacin de
HeapSort antes que el heap este inicialmente construido. La operacin de HeapSort() considera en
la etapa (a) la estructura de dato heap justamente despus de que haya sido construido por BuidHeap(), las etapas (b)-(j) son las etapas despus de las llamadas de Heapify en la lnea 5. El valor de
i es mostrado cada vez. La etapa (k) es el array ordenado resultante.
El concepto de heap se puede extender a una nueva estructura, llamada treap la cual es un binary
search tree con respecto a los elementos del nodo y un heap con respecto a las prioridades de los
nodos. De all el nombre, "treap" = "tree heap". En todo caso esta estructura la volveremos a ver
para cuando veamos rboles y sus rotaciones.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
A continuacin vemos un ejemplo de cmo trabaja RadixSort, el cual hace una primera pasada, en
orden por el 3er dgito, desde izquierda a derecha, anlogamente por el segundo dgito y finalmente
por el primer dgito. Tal como se muestra a continuacin. La flecha indica la posicin del dgito que
ser ordenado, el procedimiento asume que todos los elementos en el array A tienen d-dgitos.
Sin embargo, es factible obtener un peor caso. Por ejemplo, dado un arreglo de 10 elementos de 4
dgitos cada uno con los que Radix-Sort alcanza su peor comportamiento cuando se usa
InsertionSort para ordenar cada dgito, 0909 1818 2727 3636 4545 5454 6363 7272
8181
9090. En efecto, si se ejecuta Radix-Sort sobre esta secuencia de nmeros usando
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
InsertionSort para ordenar cada dgito, al ordenar el dgito menos significativo se alcanza el peor
comportamiento ya que estos se encuentran ordenados de mayor a menor. Despus de ordenar el
dgito menos significativo, el conjunto de los segundos dgitos significativos quedan ordenados de
mayor a menor generando nuevamente el peor comportamiento para InsertionSort, lo mismo pasa
con los siguientes dos dgitos. Es interesante entonces el considerar casos mejor, peor y promedio.
Algunos resultados interesante
Dado n n de d-dgitos en el cual todo dgito puede tomar k valores posibles, RADIXSORT
ordena correctamente estos n en tiempo (d(n + k)).
Ejemplo:
Probar que n enteros en el rango de 1 a n2 se pueden ordenar en tiempo O(n). En efecto, el nmero
de dgitos utilizado para representar n2 nmeros diferentes en un sistema de nmeros k-ario es:
logk(n2). Entonces, considerando los n2 nmeros como nmeros en radix-n, tenemos que d = logn(n2)
= 2 logn(n) = 2. Por lo tanto, necesitamos 2 dgitos, es decir, d = 2. Por otro lado, cada dgito
requiere n smbolos (radix-n), por lo que k = n. Entonces T(n) = (d(n + k)) = (2(n + n)) = (n).
Para cuando d es constante y k = O(n), radix sort corre en tiempo lineal.
Notar que si escogemos r = log(n) implica que T(n,b) = (bn/log(n)). De donde para n en el rango
de 0 a nd 1, se tiene que b = d log(n), de donde radixSort corre en tiempo = (dn).
Ordenacin mediante direcciones (BucketSort)
En BucketSort, la entrada A1, A2, , AN debe consistir solamente de enteros positivos menores que
M. El algoritmo toma un array llamado en esta oportunidad B, de tamao M, el cual es inicializado
a 0s. Luego, B tiene M celdas, o buckets, las que estn inicialmente vaca. Mientras Ai es ledo se
va incrementando B[i] en 1, segn la frecuencia de las claves. Despus que toda la entrada haya sido
leda, se escanea el array B, imprimiendo una representacin de la lista ordenada. Un ejemplo se
muestra a continuacin sobre un array de 8 elementos, los cuales son: 3, 6, 4, 1, 3, 4, 1, 4
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
LOOP 1
LOOP 2
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
LOOP 3
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
LOOP 4
En resumen se tiene,
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
Se puede verificar que este algoritmo es estable en general, lo que significa que puede ser usado
para aplicarlo en el ordenamiento RadixSort. No obstante, existen ciertos parmetros sobre el
tiempo de ejecucin de los algoritmos que hemos vistos y que funcionan a travs de comparaciones,
es decir, no se considera el resultado siguiente para los algoritmos RadixSort, CountingSort y
BucketSort
Teorema
Cualquier algoritmo de ordenamiento que funcione a travs de comparaciones requiere (n lg n)
comparaciones en el caso peor.
Para justificar lo anterior, consideremos los rboles de decisin que ayudan a aclarar esta
afirmacin. A continuacin se muestra un rbol de decisin en donde todo nodo interno es rotulado
i : j para i, j {1, 2,, n}. El subrbol izquierdo muestra las secuencias de comparaciones, ai aj.
El subrbol derecho muestra la secuencia de comparaciones ai aj.
Como se puede observar toda hoja contiene una permutacin p(1), p(2),, p(n), para indicar que el
orden ap(1) ap(2) ap(3) ap(4) .. ap(n) , ha sido establecido. (es decir, p(1) = a2 , p(2) = a3,
p(3) = a1 ).
Con este argumento se puede afirmar que un rbol de decisin puede modelar la ejecucin de
cualquier algoritmo de ordenamiento basado en comparaciones. Adems podemos concluir que,
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.
A continuacin, se muestran algunos criterios generales a tomar en cuenta para escoger de mejor
manera (dada una aplicacin) el mejor algoritmo de ordenamiento.
Recordar que cada algoritmo su mrito propio y se comportan de modo diferente de acuerdo a la
cantidad y la forma en que se le presenten los datos, entre otras cosas. No existe EL algoritmo de
ordenamiento que nos sirva siempre, slo existe el mejor para cada caso particular. Debe conocer a
fondo el problema que quiere resolver, y aplicar el ms adecuado. Aunque hay algunas preguntas
que te pueden ayudar a elegir:
1. Qu grado de orden tendr la informacin que va a manejar? Si la informacin va a estar
casi ordenada y no quiere complicarse, un algoritmo sencillo como el ordenamiento burbuja
ser suficiente. Si por el contrario los datos van a estar muy desordenados, un algoritmo
poderoso como Quicksort puede ser el ms indicado. Y si no puede hacer una presuncin sobre
el grado de orden de la informacin, lo mejor ser elegir un algoritmo que se comporte de
manera similar en cualquiera de estos dos casos extremos.
2. Qu cantidad de datos va a manipular? Si la cantidad es pequea, no es necesario utilizar un
algoritmo complejo, y es preferible uno de fcil implementacin. Una cantidad muy grande
puede hacer prohibitivo utilizar un algoritmo que requiera de mucha memoria adicional.
3. Qu tipo de datos quiere ordenar? Algunos algoritmos slo funcionan con un tipo especfico
de datos (enteros, enteros positivos, etc.) y otros son generales, es decir, aplicables a cualquier
tipo de dato.
4. Qu tamao tienen los registros de su lista? Algunos algoritmos realizan mltiples
intercambios (burbuja, insercin). Si los registros son de gran tamao estos intercambios son
ms lentos.
5. Requerimientos de memoria: El algoritmo puede necesitar memoria adicional para realizar su
labor. En general es preferible que no sea as, pero es comn en la programacin tener que
sacrificar memoria por rendimiento.
_____________________________________________________________________________Escuela de
Ingeniera en Computacin, Universidad de La Serena.