En este algoritmo de clasificación de radix, ¿qué representa cada variable? (Java)

Esta es una forma muy interesante de implementar el ordenamiento LSD radix. Por lo general, las clasificaciones de radix se hacen en binario, pero este ha elegido ordenar por dígitos decimales.

n es el número de números en los datos, el último en ser ordenado.

m es el número más grande en la matriz. El primer bucle for lo busca y lo encuentra.

El ciclo while se ejecutará [math] \ log_ {10} (m) [/ math] veces, pero en lugar de precalcular este recuento, elige incrementar la exp a través de potencias de diez y dividir cada potencia en m hasta que la exceda . (¿Por qué no simplemente verificar si lo excede? ¿Quién escribió este código?)

Cada iteración del ciclo while crea un nuevo cubo de 10 pulgadas (porque no es como dispersar un montón de pequeñas matrices por todo el montón va a hacer que un recolector de basura de todo el mundo sea más lento, ¿verdad?), Uno para cada dígitos 0 a 9. Los bucles for debajo de este primero cuentan el número de apariciones del dígito en cuestión en la posición actual del valor posicional de cada número en la lista que se debe ordenar, luego encuentre las sumas acumulativas de dígitos desde 0 hasta 9, luego, en base a estos puntos de interrupción, copia los números de la lista de datos en las posiciones apropiadas en b, una matriz temporal, luego los copia de nuevo a los datos en su nuevo orden.

Finalmente, exp se incrementa a la siguiente potencia de 10.

Creo que el hecho de que b solo tiene una longitud 10 es un error, a menos que esto esté destinado a ordenar solo las listas de longitud 10.

Sugeriría encontrar un ejemplo de otra fuente, ya que esta parece ser inusual y poco confiable.

Solo por el placer de hacerlo, aquí hay un tipo de radix LSB binario estable, marginalmente optimizado y no probado que debería ejecutarse un poco más rápido de lo que lo haría en todas las entradas excepto las más grandes:

public void radixSort (int [] data) {
int n = data.length;
int m = datos [0];
para (int i = 0; i <n; i ++)
if (datos [i]> m)
m = datos [i];
c = Integer.numberOfTrailingZeroes (Integer.highestOneBit (m)) + 1;
int izquierda, derecha
int t [];
int temp [] = nuevo int [n];
// para cada posición de bit
para (bit = 0; bit <c; bit ++) {
izquierda = 0;
derecha = n-1;
// elimina los elementos con este bit establecido al final y sin establecer al principio
para (i = 0; i <n; i ++) {
if ((datos [i] >> bit) & 1 == 0)
temp [left ++] = datos [i];
if ((datos [n-1-i] >> bit) & 1)
temp [derecha–] = datos [n-1-i];
}
t = datos;
datos = temp;
temp = t;
}
si (c% 2) {
para (i = 0; i <n; i ++) {
temp [i] = datos [i];
}
}
}

El bucle externo irá probablemente el doble de veces, pero solo hay un paso por la lista en bucles internos, en comparación con tres en la versión decimal anterior. Además, utiliza la misma matriz temporal una y otra vez en comparación con el ejemplo, ahorrando también memoria. El ahorro en los factores constantes debería convertirlo en la opción preferida en la mayoría de los casos. (No tengo un entorno Java configurado aquí, así que siéntete libre de sugerir parches si no funciona).

Además, hay tipos de radix que utilizan la ordenación in situ, pero tienden a depender en gran medida del tipo de datos que se ordenan. Ordenar números enteros, por ejemplo, puede requerir intercambiar elementos de la lista con índices. La clasificación de cadenas puede requerir otros trucos como se demuestra en este documento: http://user.it.uu.se/~arnea/ps/r…

Esto no es Java. Esta es una mala traducción del código C a Java, con un error evidente en cómo se declara b (debería ser new int[n]; ).

Aquí está el código correctamente particionado. Comprender cualquiera de los bits constituyentes debe ser casi trivial. Para completar, repasaré brevemente por qué la clasificación por radix funciona en absoluto, en ternary. Tome una matriz [3, 5, 1, 7, 18, 14]. En ternario, esto es [010, 012, 001, 021, 200, 112]. Agrupe elementos con el mismo último dígito juntos en orden creciente, pero no cambie su orden relativo dentro del grupo : [010, 200, 001, 021, 012, 112]. Ahora agrupe los elementos con el mismo penúltimo dígito, pero manteniendo la misma restricción: [200, 001, 010, 012, 112, 021]. Repita con el primer dígito: [001, 010, 012, 021, 112, 200]. Ahí tienes, la matriz está ordenada, y puedes convertirla de nuevo desde ternary: [1, 3, 5, 7, 14, 18].

Esto funciona, porque en cada paso introducimos un ordenamiento parcial de la matriz. Después de un paso, los últimos dígitos de los números están en orden. Después de dos pasos, los dos últimos dígitos de los números están ahora en orden. Después de haber agotado todos los dígitos del número más grande, la matriz está completamente ordenada.

La mejor manera de entender este código es escribiéndolo usted mismo.

Debe tener una idea clara del algoritmo:

  • Ir a través de todas las posiciones de dígitos de derecha a izquierda (el ciclo while)
  • Reordene los datos para que todos los elementos que tengan un 0 en esa posición, primero, luego todos los elementos que tengan un 1 en esa posición, y así sucesivamente (esto lo hacen todos los bucles for)

Solo piense en cómo haría que la computadora hiciera esos dos pasos, y estoy seguro de que encontrará que su solución coincide exactamente con lo que está haciendo ese código.

Tengo la impresión de que hay un error en el código: la matriz b debe declararse como una matriz int que es n larga (esto se puede ver claramente en el último bucle for, donde b está indexado a la posición n, en lugar de 10)

(También realmente no me gusta el último bucle for; intercambiar los datos y las matrices b es mucho más rápido que copiar todo).