parcial 2 algoritmos grupo 6

Anuncio
ALGORITMOS DE ORDENAMIENTO
COUNTING SORT
CHRISTIAN ESTEBAN ALDANA ROZO
BRAYAN STIF FORERO CRUZ
GIOVANNY GUZMÁN CÉSPEDES
JORGE MEJIA
Profesora:
DIANA MABEL DIAZ
UNIVERSIDAD PILOTO DE COLOMBIA
INGENIERIA DE SITEMAS
ANALISIS Y DISEÑO DE ALGORTIMOS
BOGOTA D.C.
2010
HISTORIA
El algoritmo de ordenamiento Counting Sort (Ordenamiento por Cuentas en español) es un
algoritmo de ordenamiento en el que se cuenta el número de elementos de cada clase para luego
ordenarlos. Sólo puede ser utilizado por tanto para ordenar elementos que sean contables, por
ejemplo, los números enteros de un determinado intervalo, sin contar números reales.
El algoritmo fue creado por Harold H. Seward en 1954,
ANÁLISIS DEL ALGORITMO
El primer paso consiste en averiguar cuál es el intervalo dentro del que están los datos a ordenar
(valores mínimo y máximo). Después se crea un vector de números enteros con tantos elementos
como valores haya en el intervalo [mínimo, máximo], y a cada elemento se le da el valor 0 (0
apariciones). Tras esto se recorren todos los elementos a ordenar y se cuenta el número de
apariciones de cada elemento (usando el vector que hemos creado). Por último, basta con
recorrer este vector para tener todos los elementos ordenados.
Se trata de un algoritmo estable cuya complejidad computacional es O(n+k), siendo n el número
de elementos a ordenar y k el tamaño del vector auxiliar (máximo - mínimo). Si este último
intervalo es muy amplio, el algoritmo es ineficiente, ya que el vector auxiliar tiene un tamaño
excesivamente grande, lo que supondría un gran coste en memoria y también en tiempo.
Con lenguajes de programación que no permitan definir vectores cuyo primer índice sea un valor
distinto de 0 ó 1 es necesario realizar una traducción de los valores. Por ejemplo, si el intervalo es
[4,10] y el vector auxiliar se define como vaux = vector[1..7], el valor 6 deberá incrementar el
contador de la posición vaux[3].Si en lugar de esta simple traducción se utilizan funciones más
complejas, entonces el algoritmo se denominaría bucket sort.
Counting sort es un algoritmo de ordenamiento similar al algoritmo de Bucket sort, este algoritmo
tiene la ventaja de conocer el rango de los números de la matriz a ordenar (matriz A). Utiliza este
rango para crear una matriz C de esta longitud. Cada índice i en C matriz se utiliza para contar el
número de elementos en una cuenta con el valor, y luego cuenta almacenada en C se puede
utilizar para poner los elementos de A en su posición correcta en la matriz resultante ordenados.
El algoritmo fue creado por Harold H. Seward en 1954.
CORRECTITUD
INICIO:
En el desarrollo del algoritmo se tienen como datos de entrada números con un rango entre cero y
k (0≤ Sn ≥ K), es decir que el primer paso del algoritmo será verificar si todos los elementos a
ordenar son menores o iguales que k.
El algoritmo también deberá encontrar el valor de Px quien es el que representa la cantidad de
elementos de entrada que son menores o iguales a x (0≤ Sn ≥ K). Así por ejemplo si Psi es igual a K
sabemos que podemos insertar a Si directamente en la posición K en el arreglo de salida, ya que
entre los elementos que queremos ordenar hay exactamente K elementos menores que S1.
MANTENIMIENTO (INVARIANTE)
Cuidado especial se debe tener cuando el arreglo de entrada contiene elementos repetidos.
FINALIZACIÓN
Después que los datos de entrada han pasado por los diferentes ciclos de este algoritmo, finalizara
cuando todos los valores de entrada estén en su posición correspondiente.
En el primer ciclo sólo cuenta solo cuantos valores iguales a x existen y los almacena en un vector
P[x]. En el segundo ciclo hace una suma acumulativa para que finalmente P[x] almacene la
cantidad de valores que son menores o iguales a x. En el ciclo final se inserta cada elemento
directamente en la posición que le corresponde. Si el valor x no se encuentra repetido en A, su
posición final será directamente P[x]−1. Ahora si x se encuentra repetido en A su posición final
dependerá de cuantos valores iguales a x se hayan insertado ya en el arreglo final, por esto
después de insertar a x se decrementa el valor de P[x].
COMPLEJIDAD
La primera observación importante del procedimiento Counting-Sort tiene que ver con su
complejidad. El primer y último ciclo toman tiempo lineal con respecto a n, y el ciclo intermedio
toma tiempo lineal con respecto a k, por lo que el tiempo total para countingsort es O(n +k). Esto
nos dice que en una situación práctica en la que k sea O(n), countingsort tardará tiempo lineal con
respecto a n, O(n) en el peor caso mejorando la cota (n log n). La segunda observación tiene que
ver con esto ´ultimo, countingsort en ningún momento realiza comparaciones entre los elementos
que se quieren ordenar por lo que la cota (n log n) no es válida para ´el. Como última observación
alguien podría preguntarse por qué el último ciclo es desde n−1 a 0 y no desde 0 a n−1. De hecho,
si el ciclo se realizara aumentando el contador, Counting-Sort seguiría ordenando los valores. El
ciclo se hace decrementando el contador para darle a Counting-Sort la importante propiedad de
ser estable. Un algoritmo de ordenación es estable cuando para cada par de elementos iguales,
estos aparecen finalmente en el mismo orden en el que aparecían en el arreglo inicial. En el
próximo algoritmo que estudiemos veremos la importancia de esta propiedad.
ORDEN DE COMPLEJIDAD
LINEA DE CODIGO
COMPLEJIDAD
Random rnd = new Random();
1
rnd.nextInt();
1
int[] A = new int[100000];
1
for (long i=0; i < 1000000; i++) {
n
int n =
n depende del número de iteraciones,
(int)(rnd.nextDouble()*100000);
que para este caso específico es
A[n]++;}
1000000.
for (long i=0; i < 1000000; i++) {
n
int n =
n depende del número de iteraciones,
(int)(rnd.nextDouble()*100000);
que para este caso específico es
A[n]++;}
1000000.
int[] B = counting_sort(A,10000);
1
for(int i=0;i<B.length;i++){
n
System.out.print(B[i]+" : "+i+" , "); } n depende de la longitud del vector, que
para este caso específico es 10000.
int[] C = new int[k+1];
1
int[] B = new int[A.length];
n
n depende de la longitud del vector, que
para este caso específico es 10000.
for(int i=0;i<=k;i++){
n
C[i]=0; }
n depende del número de iteraciones k,
k es igual a la longitud del vector C.
for(int j=0;j<A.length;j++){
n
C[A[j]]+=1; }
n depende de la longitud del vector, que
para este caso específico es 100000.
for(int i=1;i<=k;i++){
n
C[i]+=C[i-1]; }
n depende del número de iteraciones k,
k es igual a la longitud del vector C.
for(int j=A.length-1;j>=0;j--){
n
B[C[A[j]]-1]=A[j];
n depende de la longitud del vector, que
C[A[j]]-=1; }
para este caso específico es 100000
return B;
1
Tiempo de Ejecución
n=10
n=100
n=1000
n=10000
n=100000
En conclusión podemos decir que el algoritmo es de tipo n2
Descargar