Está en la página 1de 6

Ordenamiento de distribucin por conteo Un problema que se presenta con frecuencia es el siguiente: Ordenar un archivo con N registros cuyas

llaves son enteros comprendidos entre 0 y M-1. Si M no es muy grande, se puede usar el algoritmo de distribucin por conteo. La idea bsica es contar el nmero de veces que se repite cada llave diferente y en una segunda pasada utilizar el conteo para posicionar los registros en el archivo. void distributioncounting (itemType a[], int N, int M) { itemType *b; b = new itemType [N]; int *count; count = new int[M]; int i, j; for (j = 0; j < M; j++) count [j] = 0; for (i = 1; i <= N; i++) count [a] ++; for (j = 1; j < M; j++) count [j] += count[j - 1]; for (i = N; i >= 1; i--) b[count[a]--] = a ; for (i = 1; i <= N; i++) a = b; delete b; delete count; } Definicin En muchas aplicaciones se puede aprovechar el hecho de que las llaves se pueden representar como nmeros dentro de un rango restringido. Se denominan ordenamientos radix a los mtodos que sacan ventaja de las propiedades digitales de estos nmeros. Estos mtodos no comparan llaves; sino que procesan y comparan pedazos de llaves. Los algoritmos de ordenamiento radix trabajan sobre dgitos individuales de los nmeros que representan a las llaves cuando estas pertenecen a un sistema numrico base M (el radix). Muchas aplicaciones de ordenamiento pueden operar en llaves compuestas de nmeros binarios. Ordenamiento por intercambio radix. Este algoritmo se basa en ordenar las llaves de forma tal que todas las que inicien con un bit en 0 aparezcan antes que todas las que inicien con un bit en 1 y proceder sucesivamente con el resto de los bits mientras queden elementos pendientes de ordenar. Esto da lugar a un algoritmo recursivo. Para reordenar el arreglo inspeccionar comenzando por la izquierda hasta encontrar una llave que empiece con un bit en 1, despus inspeccionar por la derecha hasta encontrar una llave que empiece con un bit en 0, intercambiar las llaves y continuar hasta que se crucen los apuntadores de ambas inspecciones. void radixexchange (itemType a[], int left, int right, int bit) { int i, j; itemType t; if (right > left && bit >= 0) { i = left; j = right; while (j != i)

{ while (!a.bits (bit, 1) && i < j) i++; while ( a[j].bits (bit, 1) && j > i) j--; swap (a, i, j); } if (!a[right].bits (bit, 1)) j++; radixexchange (a, left, j - 1, bit - 1); radixexchange (a, j, right, bit - 1); } } Este mtodo se emplea para organizar informacin por ms de un criterio. Lo que hacemos es determinar la importancia de los criterios de ordenacin y aplicar ordenacin estable tantas veces como criterios se tengan, empezando por el criterio menos importante y determinando por el criterio ms importante. Estabilidad Un algoritmo de ordenamiento se considera estable si preserva el orden relativo de llaves iguales en la estructura de datos. Por ejemplo, si queremos ordenar por calificacin una lista de asistencia que se encuentra ordenada alfabticamente, un algoritmo estable produce una lista en la que los estudiantes con el mismo grado se mantienen ordenados alfabticamente, mientras que un algoritmo inestable no dejar trazas del ordenamiento original. La mayora de los mtodos bsicos son estables, pero la mayora de los mtodos sofisticados no lo son. Ordenamiento por radix directo Una variante al mtodo de intercambio radix consiste en examinar los bits de derecha a izquierda. El mtodo depende de que el proceso de particin de un bit sea estable. Por lo que el proceso de particin utilizado en el algoritmo de intercambio radix no nos sirve; el proceso de particin es como ordenar una estructura con solo dos valores, por lo que el algoritmo de distribucin por conteo nos sirve muy bien. Si asumimos que M = 2 en el algoritmo de distribucin por conteo y reemplazamos a por bits (a, k, 1) podemos ordenar el arreglo a en sus k posiciones menos significativas usando un arreglo temporal b. Pero nos conviene ms usar un valor de M mayor que corresponda a m bits a la vez durante el ordenamiento con M = 2m como en el siguiente cdigo. void straightradix (itemType a[], itemType b[], int N) { int i, j, pass, count [M-1]; for (pass = 0; pass < numBits / m; pass++) { for (j=0; j < M; j++) count [j] = 0; for (i = 1; i <= N; i++) count [a .bits (pass * m, m)]++; for (j = 1; j < M; j++) count [j] += count [j - 1]; for (i = N; i >= 1; i--) b [count [a .bits (pass * m, m)] --] = a ; for (i = 1; i <= N; i++) a = b; }

} Anlisis de eficiencia de los ordenamientos por radix La eficiencia de este algoritmo depende en que las llaves estn compuestas de bits aleatorios en un orden aleatorio. Si esta condicin no se cumple ocurre una fuerte degradacin en el desempeo de estos mtodos. Adicionalmente, requiere de espacio adicional para realizar los intercambios. Los algoritmos de ordenamiento basados en radix se consideran como de propsito particular debido a que su factibilidad depende de propiedades especiales de las llaves, en contraste con algoritmos de propsito general como Quicksort que se usan con mayor frecuencia debido a su adaptabilidad a una mayor variedad de aplicaciones. En algunas aplicaciones a la medida, el ordenamiento por radix puede ejecutarse hasta en el doble de velocidad que Quicksort, pero no vale la pena intentarlo si existe problemas potenciales de espacio de almacenamiento o si las llaves son de tamao variable y/o no son aleatorias. Programa en Estructura de Datos C# que utiliza Ordenacin Radix (Consola) Cdigo Fuente class nodo { public int info; public int next; } class Radix { int[] x; public void Generar() { Random Aleatorio = new Random(); x = new int[50]; for (int i = 0; i < 50; i++) { x[i] = Aleatorio.Next(10210000, 10210100); } Console.WriteLine("El Arreglo a sido generado"); } public void radix() { if (x != null) { int i, k, y, expon, j, q; int p = 0; int N = 50 - 1; int M = 7; nodo[] node = new nodo[50]; int[] rear = new int[10]; int[] front = new int[11]; for (i = 0; i <= N; i++) { node[i] = new nodo(); node[i].info = x[i];

node[i].next = i + 1; } node[N].info = x[N]; node[N].next = -1; int first = 0; for (k = 1; k <= M; k++) { for (i = 0; i <= 9; i++) { rear[i] = new int(); rear[i] = -1; } for (i = 0; i <= 10; i++) { front[i] = new int(); front[i] = -1; } while (first != -1) { p = first; first = node[first].next; y = node[p].info; expon = 1; for (i = 1; i != k; i++) { expon = expon * 10; } j = (y / expon) % 10; q = rear[j]; if (q == -1) front[j] = p; else node[q].next = p; rear[j] = p; } j = 0; while (j <= 9 && front[j] == -1) j++; first = front[j]; while (j <= 9) { i = j + 1; while (i <= 9 && front[i] == -1) i++; if (i <= 9) { p = i; node[rear[j]].next = front[i]; }

j = i; } node[rear[p]].next = 0; } for (i = 0; i <= N; i++) { x[i] = node[first].info; first = node[first].next; } Console.WriteLine("El arreglo a sido ordenado"); } else { Console.WriteLine("No se ha creado un arreglo"); } } public void Desplegar() { if (x != null) { int c = 0; int pos = 0; Console.Write("\n"); for (int i = 0; i < 10; i++) { for (int j = 0; j < 5; j++) { pos++; Console.Write("{0,2}:{1,3}\t", pos, x[c]); c++; } Console.Write("\n"); } } else { Console.WriteLine("No se ha creado un arreglo"); } } } static void Main(string[] args) { Radix rx = new Radix(); int Opcion; do { Console.Clear(); Console.WriteLine("MENU RADIX");

Console.WriteLine("1) Generar "); Console.WriteLine("2) Desplegar "); Console.WriteLine("3) Ordenar "); Console.WriteLine("4) Salir "); Console.Write("Introduce una opcion:"); Opcion = Int32.Parse(Console.ReadLine()); switch (Opcion) { case 1: Console.Clear(); rx.Generar(); Console.ReadLine(); break; case 2: Console.Clear(); rx.Desplegar(); Console.ReadLine(); break; case 3: Console.Clear(); rx.radix(); Console.ReadLine(); break; case 4: Console.WriteLine("\n\nPresione <ENTER> Para Salir"); Console.ReadLine(); break; default: Console.Clear(); Console.WriteLine("Opcion Invalida"); Console.ReadLine(); break; } } while (Opcion != 4); }