Articulo de referencia

Clasificación por cubos

O\\left(n^2\\right) "},"average-time":{"wt":" O\\left(n+\\frac{n^2}{k}+k\\right) , where k is the number of buckets. O(n), \\text {when } k \\approx n ."},"space":{"wt":" O(n + ...

Los elementos se distribuyen entre contenedores.
Luego, los elementos se clasifican dentro de cada contenedor.

El ordenamiento por cubetas , o ordenamiento por contenedores , es un algoritmo de ordenamiento que funciona distribuyendo los elementos de un arreglo en varias cubetas. Cada cubeta se ordena individualmente, ya sea utilizando un algoritmo de ordenamiento diferente o aplicando recursivamente el algoritmo de ordenamiento por cubetas. Es un ordenamiento por distribución , una generalización del ordenamiento por palomar que permite múltiples claves por cubeta, y es similar al ordenamiento por radix en la variante de dígito más significativo a menos significativo. El ordenamiento por cubetas se puede implementar con comparaciones y, por lo tanto, también se puede considerar un algoritmo de ordenamiento por comparación . La complejidad computacional depende del algoritmo utilizado para ordenar cada cubeta, la cantidad de cubetas a utilizar y si la entrada está distribuida uniformemente.

El sistema de ordenación por cubetas funciona de la siguiente manera:

  1. Configura una matriz de "cubos" inicialmente vacíos.
  2. Dispersión : Recorre el array original, colocando cada objeto en su cubo correspondiente.
  3. Clasifica cada cubo que no esté vacío.
  4. Recopilar : Visita los cubos en orden y vuelve a colocar todos los elementos en el array original.

Pseudocódigo

La función bucketSort(array, k) es cubos ← nueva matriz de k listas vacías M ← 1 + el valor máximo de la clave en el array para i = 0 hasta length(array) hacer insertar array[i] en buckets[floor(k × array[i] / M)] para i = 0 hasta k hacer nextSort(buckets[i]) Devuelve la concatenación de buckets[0], ..., buckets[k]

Sea array el arreglo que se va a ordenar y k el número de cubetas que se van a usar. Se puede calcular el valor máximo de la clave en tiempo lineal iterando sobre todas las claves una vez. Se debe usar la función floor para convertir un número de punto flotante a un entero (y posiblemente también para la conversión de tipos de datos). La función nextSort es una función de ordenación que se usa para ordenar cada cubeta. Convencionalmente, se usa la ordenación por inserción debido a su rendimiento relativamente alto con un número pequeño de elementos, pero también se podrían usar otros algoritmos, como la ordenación por selección o la ordenación por fusión . Usar bucketSort como nextSort produce un pariente de la ordenación por radix ; en particular, el caso n = 2 corresponde a quicksort (aunque potencialmente con malas elecciones de pivote).

Análisis

Análisis del peor escenario

Cuando la entrada contiene varias claves cercanas entre sí (agrupación), es probable que esos elementos se coloquen en el mismo cubo, lo que da como resultado que algunos cubos contengan más elementos de lo normal. El peor escenario se produce cuando todos los elementos se colocan en un solo cubo. En ese caso, el rendimiento general estaría dominado por el algoritmo utilizado para ordenar cada cubo, por ejemploO(norte2){\displaystyle O(n^{2})}ordenación por inserción oO(norteregistro(norte)){\displaystyle O(n\log(n))}algoritmos de ordenación por comparación , como la ordenación por fusión .

Análisis del caso promedio

Consideremos el caso en que la entrada se distribuye uniformemente. El primer paso, que consiste en inicializar los cubos y encontrar el valor máximo de la clave en el array, se puede realizar enO(norte){\displaystyle O(n)}tiempo. Si la división y la multiplicación se pueden realizar en tiempo constante, entonces dispersar cada elemento en su cubo también cuesta.O(norte){\displaystyle O(n)}. Supongamos que se utiliza el ordenamiento por inserción para ordenar cada cubo, entonces el tercer paso cuestaO(i=1knortei2){\displaystyle O(\textstyle \sum _ {i=1}^{k}\displaystyle n_ {i}^{2})}, dóndenortei{\displaystyle n_{i}}es la longitud del cubo indexadoi{\displaystyle i}. Dado que nos referimos al tiempo promedio, la expectativami(nortei2){\displaystyle E(n_{i}^{2})}en su lugar debe evaluarse.incógnitaij{\displaystyle X_{ij}}sea ​​la variable aleatoria que es1{\displaystyle 1}si elementoj{\displaystyle j}se coloca en el cuboi{\displaystyle i}, y0{\displaystyle 0}de lo contrario. Tenemosnortei=j=1norteincógnitaij{\displaystyle n_{i}=\sum _{j=1}^{n}X_{ij}}. Por lo tanto,

mi(nortei2)=mi(j=1norteincógnitaijl=1norteincógnitail)=mi(j=1nortel=1norteincógnitaijincógnitail)=mi(j=1norteincógnitaij2)+mi(1j,lnortejlincógnitaijincógnitail).{\displaystyle {\begin{aligned}E(n_{i}^{2})&=E\left(\sum _{j=1}^{n}X_{ij}\sum _{l=1}^{n}X_{il}\right)\\&=E\left(\sum _{j=1}^{n}\sum _{l=1}^{n}X_{ij}X_{il}\right)\\&=E\left(\sum _{j=1}^{n}X_{ij}^{2}\right)+E\left(\sum _{1\leq j,l\leq n}\sum _{j\neq l}X_{ij}X_{il}\right).\end{aligned}}}

La última línea separa la suma en el casoj=l{\displaystyle j=l}y el casojl{\displaystyle j\neq l}. Dado que la probabilidad de que un objeto se distribuya al cubo es baja.i{\displaystyle i}es1/k{\displaystyle 1/k},incógnitaij{\displaystyle X_{ij}}es 1 con probabilidad1/k{\displaystyle 1/k}y 0 en caso contrario.

mi(incógnitaij2)=12(1k)+02(11k)=1k{\displaystyle E(X_{ij}^{2})=1^{2}\cdot \left({\frac {1}{k}}\right)+0^{2}\cdot \left(1-{\frac {1}{k}}\right)={\frac {1}{k}}}
mi(incógnitaijincógnitaik)=1(1k)(1k)=1k2{\displaystyle E(X_{ij}X_{ik})=1\cdot \left({\frac {1}{k}}\right)\left({\frac {1}{k}}\right)={\frac {1}{k^{2}}}}

Con la suma, sería

mi(j=1norteincógnitaij2)+mi(1j,knortejkincógnitaijincógnitaik)=norte1k+norte(norte1)1k2=norte2+norteknortek2{\displaystyle E\left(\sum _{j=1}^{n}X_{ij}^{2}\right)+E\left(\sum _{1\leq j,k\leq n}\sum _{j\neq k}X_{ij}X_{ik}\right)=n\cdot {\frac {1}{k}}+n(n-1)\cdot {\frac {1}{k^{2}}}={\frac {n^{2}+nk-n}{k^{2}}}}

Finalmente, la complejidad seríaO(i=1kmi(nortei2))=O(i=1knorte2+norteknortek2)=O(norte2k+norte){\displaystyle O\left(\sum _{i=1}^{k}E(n_{i}^{2})\right)=O\left(\sum _{i=1}^{k}{\frac {n^{2}+nk-n}{k^{2}}}\right)=O\left({\frac {n^{2}}{k}}+n\right)}.

El último paso del algoritmo de ordenación por cubetas, que consiste en concatenar todos los objetos ordenados en cada cubeta, requiereO(k){\displaystyle O(k)}tiempo. Por lo tanto, la complejidad total esO(norte+norte2k+k){\displaystyle O\left(n+{\frac {n^{2}}{k}}+k\right)}. Tenga en cuenta que si k se elige comok=Θ(norte){\displaystyle k=\Theta (n)}, luego se ejecuta la ordenación por cubetas enO(norte){\displaystyle O(n)}tiempo promedio, dada una entrada distribuida uniformemente. [ 1 ]

Optimizaciones

Una optimización común consiste en volver a colocar primero los elementos no ordenados de los cubos en el array original y, a continuación, ejecutar el algoritmo de ordenación por inserción sobre el array completo; dado que el tiempo de ejecución de la ordenación por inserción se basa en la distancia de cada elemento a su posición final, el número de comparaciones sigue siendo relativamente pequeño y la jerarquía de memoria se aprovecha mejor almacenando la lista de forma contigua en la memoria. [ 2 ]

Si se conoce o se puede estimar la distribución de entrada, a menudo se pueden elegir cubetas que contengan una densidad constante (en lugar de tener simplemente un tamaño constante). Esto permiteO(norte){\displaystyle O(n)}Complejidad temporal promedio incluso sin entrada distribuida uniformemente.

Variantes

Clasificación genérica por cubetas

La variante más común del algoritmo de ordenación por cubetas opera sobre una lista de n entradas numéricas entre cero y un valor máximo M , dividiendo el rango de valores en b cubetas, cada una de tamaño M / b . Si cada cubeta se ordena mediante el algoritmo de ordenación por inserción , se puede demostrar que la ordenación se ejecuta en tiempo lineal esperado (donde se toma el promedio sobre todas las entradas posibles). [ 3 ] Sin embargo, el rendimiento de esta ordenación se degrada con la agrupación; si muchos valores aparecen muy cerca unos de otros, todos caerán en una sola cubeta y se ordenarán lentamente. Esta degradación del rendimiento se evita en el algoritmo original de ordenación por cubetas asumiendo que la entrada se genera mediante un proceso aleatorio que distribuye los elementos uniformemente en el intervalo [0,1) . [ 1 ]

Ordenar por mapa de proximidad

De forma similar al algoritmo de ordenación por cubetas genérico descrito anteriormente, ProxmapSort funciona dividiendo una matriz de claves en submatrices mediante una función de "clave de mapa" que conserva un orden parcial de las claves. A medida que cada clave se agrega a su submatriz, se utiliza la ordenación por inserción para mantenerla ordenada, de modo que toda la matriz quede ordenada cuando ProxmapSort finaliza. ProxmapSort se diferencia de la ordenación por cubetas en el uso de la clave de mapa para ubicar los datos aproximadamente donde les corresponde en el orden ordenado, generando un "proxmap" (un mapeo de proximidad) de las claves.

Ordenación por histograma

Otra variante del algoritmo de ordenación por cubetas, conocida como ordenación por histograma o ordenación por conteo, añade una pasada inicial que cuenta el número de elementos que caerán en cada cubeta mediante un arreglo de conteo. [ 4 ] Con esta información, los valores del arreglo se pueden organizar en una secuencia de cubetas in situ mediante una secuencia de intercambios, sin generar sobrecarga de espacio para el almacenamiento de cubetas.

Del tipo del cartero

El algoritmo de ordenación del cartero es una variante del algoritmo de ordenación por cubetas que aprovecha una estructura jerárquica de elementos, generalmente descrita por un conjunto de atributos. Este es el algoritmo que utilizan las máquinas clasificadoras de correos : el correo se clasifica primero entre nacional e internacional; luego por estado, provincia o territorio; luego por oficina de correos de destino; luego por rutas, etc. Dado que las claves no se comparan entre sí, el tiempo de clasificación es O( cn ), donde c depende del tamaño de la clave y del número de cubetas. Esto es similar a un algoritmo de ordenación por radix que funciona "de arriba hacia abajo" o "de arriba al dígito más significativo primero". [ 5 ] [ 6 ]

Ordenar de forma aleatoria

El algoritmo de ordenación por mezcla [ 7 ] es una variante del algoritmo de ordenación por cubetas que comienza eliminando el primer octavo de los n elementos a ordenar, los ordena recursivamente y los coloca en un arreglo. Esto crea n /8 "cubetas" en las que se distribuyen los 7/8 elementos restantes. Cada "cubeta" se ordena y las "cubetas" se concatenan en un arreglo ordenado.

Comparación con otros algoritmos de ordenación

El algoritmo de ordenación por cubetas puede considerarse una generalización del algoritmo de ordenación por conteo ; de hecho, si cada cubeta tiene un tamaño de 1, este algoritmo se reduce al algoritmo de ordenación por conteo. El tamaño variable de las cubetas en este algoritmo le permite usar memoria O( n ) en lugar de memoria O( M ), donde M es el número de valores distintos; a cambio, renuncia al comportamiento en el peor de los casos O( n + M ) del algoritmo de ordenación por conteo.

El algoritmo de ordenación por cubetas con dos cubetas es, en esencia, una versión de ordenación rápida donde el valor pivote siempre se selecciona como el valor medio del rango de valores. Si bien esta elección es eficaz para entradas distribuidas uniformemente, otros métodos para seleccionar el pivote en la ordenación rápida, como la selección aleatoria de pivotes, la hacen más resistente a la agrupación en la distribución de entrada.

El algoritmo de ordenación por fusión de n vías también comienza dividiendo la lista en n sublistas y ordenando cada una; sin embargo, las sublistas creadas por este algoritmo tienen rangos de valores superpuestos, por lo que no pueden recombinarse mediante una simple concatenación como en la ordenación por cubetas. En su lugar, deben intercalarse mediante un algoritmo de fusión. No obstante, este coste adicional se compensa con la fase de dispersión más sencilla y la capacidad de garantizar que cada sublista tenga el mismo tamaño, lo que proporciona un buen límite de tiempo en el peor de los casos.

La ordenación por radix descendente puede considerarse un caso especial de la ordenación por cubetas, donde tanto el rango de valores como el número de cubetas están restringidos a ser potencias de dos. En consecuencia, el tamaño de cada cubeta también es una potencia de dos, y el procedimiento puede aplicarse de forma recursiva. Este enfoque puede acelerar la fase de dispersión, ya que solo necesitamos examinar un prefijo de la representación binaria de cada elemento para determinar su cubeta.

Referencias

  1. 1 2 Thomas H. Cormen ; Charles E. Leiserson ; Ronald L. Rivest y Clifford Stein . Introducción a los algoritmos . El ordenamiento por cubetas se ejecuta en tiempo lineal en promedio. Al igual que el ordenamiento por conteo, el ordenamiento por cubetas es rápido porque asume algo sobre la entrada. Mientras que el ordenamiento por conteo asume que la entrada consiste en enteros en un rango pequeño, el ordenamiento por cubetas asume que la entrada es generada por un proceso aleatorio que distribuye los elementos uniformemente en el intervalo [0,1) . La idea del ordenamiento por cubetas es dividir el intervalo [0, 1) en n subintervalos de igual tamaño, o cubetas, y luego distribuir los n números de entrada en las cubetas. Dado que las entradas están distribuidas uniformemente en [0, 1) , no esperamos que muchos números caigan en cada cubeta. Para producir la salida, simplemente ordenamos los números en cada cubeta y luego recorremos las cubetas en orden, listando los elementos en cada una.
  2. Corwin, E. y Logar, A. «Ordenación en tiempo lineal: variaciones del algoritmo de ordenación por cubetas». Journal of Computing Sciences in Colleges , 20, 1, pp. 197-202. Octubre de 2004.
  3. Thomas H. Cormen , Charles E. Leiserson , Ronald L. Rivest y Clifford Stein . Introducción a los algoritmos , segunda edición. MIT Press y McGraw-Hill, 2001. ISBN 0-262-03293-7. Sección 8.4: Clasificación por cubetas, págs. 174 177.
  4. Diccionario de algoritmos y estructuras de datos del NIST: ordenación por histograma
  5. Black, Paul E., ed. (20 de junio de 2011). "ordenación del cartero" . Diccionario de algoritmos y estructuras de datos . Instituto Nacional de Estándares y Tecnología . Recuperado el 31 de marzo de 2026 .Dominio públicoEste artículo incorpora texto de esta fuente, que es de dominio público .
  6. Ramey, Robert (agosto de 1992). "The Postman's Sort" . C/C++ Users Journal . Archivado del original el 28 de junio de 2009.
  7. Una nueva y revolucionaria propuesta de John Cohen, 26 de noviembre de 1997
  • Diccionario de algoritmos y estructuras de datos del NIST: ordenación por cubetas
  • Código de clasificación de cubeta para Ansi C
  • Variante del algoritmo de ordenación por cubetas con demostración