La ordenación por interpolación (o ordenación por histograma) es un algoritmo de ordenación que utiliza una fórmula de interpolación para dividir y conquistar . [ 1 ] Es una variante de la ordenación por cubetas . Los datos se asignan a cubetas utilizando una función de interpolación: donde y son los valores mínimo y máximo dentro del arreglo, y se utiliza la función floor . Esta función devuelve un índice del arreglo donde el elemento puede ser reposicionado.
Algoritmo
La ordenación por interpolación utiliza una matriz de longitudes de cubetas de registros que corresponden a la columna numérica original. La matriz evita que la complejidad espacial aumente debido al apilamiento de memoria. El registro de segmentación de la matriz de longitudes puede, mediante una función secundaria, declarar y eliminar dinámicamente el espacio de memoria de la matriz . La complejidad espacial requerida para controlar el programa recursivo es . Contiene una matriz bidimensional de memorias asignadas dinámicamente y una matriz de longitudes de registros. Sin embargo, la complejidad de ejecución aún puede mantenerse como un método de ordenación eficiente de .
La matriz de memoria asignada dinámicamente puede implementarse utilizando un objeto de matriz (como en JavaScript ) o, más básicamente, mediante una lista enlazada , pila , cola , matriz asociativa o estructura de árbol . El tipo de estructura de datos afecta la velocidad de acceso a los datos y, por lo tanto, el tiempo de ordenación. Cuando los valores en la matriz ordenada están distribuidos uniformemente en una progresión aritmética , el orden de ordenación por interpolación es de tiempo lineal .
Algoritmo de ordenación por interpolación
- Establezca una matriz de longitud de cubeta para registrar la longitud de la cubeta sin ordenar. Inicialícela con la longitud de la matriz original.
- [Ordenación principal] Si se vacía el array de longitud de cubeta, la ordenación se completa. De lo contrario, se ejecuta la función Divide.
- [Función Divide] Extrae el cubo al final del array de longitud de cubo. Encuentra los valores máximo y mínimo en el cubo. Si el valor máximo es igual al valor mínimo, el cubo está ordenado, así que detén la función Divide.
- Crea una matriz bidimensional con todos los cubos vacíos. Divide los datos en los cubos según el número de interpolación.
- Después de dividir en cubetas, agregue la longitud de cada cubeta a la matriz de longitud de cubeta. Luego, vuelva a colocar los elementos de todas las cubetas que no estén vacías en la matriz original, uno por uno.
- Volver a [Ordenar principal].
Algoritmo de ordenación por histograma
El NIST describe la ordenación por histograma como un refinamiento eficiente de 3 pasadas de un algoritmo de ordenación por cubetas. [ 2 ]
- En la primera pasada se cuenta el número de elementos de cada cubo en una matriz auxiliar y, a continuación, se realiza un total acumulado de manera que cada entrada auxiliar sea igual al número de elementos anteriores.
- La segunda pasada coloca cada elemento en su categoría correspondiente según la entrada auxiliar para la clave de ese elemento.
- La última pasada ordena cada cubo.
Práctica
Implementación de ordenación por interpolación
Código JavaScript:
Array . prototype . interpolationSort = function () { var divideSize = new Array (); var end = this . length ; divideSize [ 0 ] = end ; while ( divideSize . length > 0 ) { divide ( this ); } // Repetir la función divide a ArrayList function divide ( A ) { var size = divideSize . pop (); var start = end - size ; var min = A [ start ]; var max = A [ start ]; for ( var i = start + 1 ; i < end ; i ++ ) { if ( A [ i ] < min ) { min = A [ i ]; } else { if ( A [ i ] > max ) { max = A [ i ]; } } } if ( min == max ) { end = end - size ; } else { var p = 0 ; var bucket = new Array ( size ); para ( var i = 0 ; i < size ; i ++ ) { bucket [ i ] = new Array (); } para ( var i = start ;i < end ; i ++ ) { p = Math . floor ((( A [ i ] - min ) / ( max - min ) ) * ( size - 1 )); bucket [ p ]. push ( A [ i ]); } for ( var i = 0 ; i < size ; i ++ ) { if ( bucket [ i ]. length > 0 ) { for ( var j = 0 ; j < bucket [ i ]. length ; j ++ ) { A [ start ++ ] = bucket [ i ][ j ]; } divideSize . push ( bucket [ i ]. length ); } } } } };Método recursivo de ordenación por interpolación
Complejidad espacial en el peor de los casos:
Array . prototype . interpolationSort = function () { //-- Edit date:2019/08/31 --// var start = 0 ; var size = this . length ; var min = this [ 0 ]; var max = this [ 0 ]; for ( var i = 1 ; i < size ; i ++ ) { if ( this [ i ] < min ) { min = this [ i ]; } else { if ( this [ i ] > max ) { max = this [ i ];} } } if ( min != max ) { var bucket = new Array ( size ); for ( var i = 0 ; i < size ; i ++ ) { bucket [ i ] = new Array (); } var interpolation = 0 ; for ( var i = 0 ; i < size ; i ++ ) { interpolation = Math . piso ((( this [ i ] - min ) / ( max - min )) * ( size - 1 )); cubo [ interpolación ]. push ( this [ i ]); } para ( var i = 0 ; i < size ;i ++ ) { if ( bucket [ i ]. length > 1 ) { bucket [ i ]. interpolationSort (); } // Recursión for ( var j = 0 ; j < bucket [ i ]. length ; j ++ ) { this [ start ++ ] = bucket [ i ][ j ]; } } } };Implementación de la ordenación por histograma
Array . prototype . histogramSort = function () { //-- Edit date:2019/11/14 --// var end = this . length ; var sortedArray = new Array ( end ); var interpolation = new Array ( end ); var hitCount = new Array ( end ); var divideSize = new Array (); divideSize [ 0 ] = end ; while ( divideSize . length > 0 ) { distribute ( this ); } // Repetir la función distribute a Array function distribute ( A ) { var size = divideSize . pop (); var start = end - size ; var min = A [ start ]; var max = A [ start ]; for ( var i = start + 1 ; i < end ; i ++ ) { if ( A [ i ] < min ) { min = A [ i ]; } else { if ( A [ i ] > max ) { max = A [ i ]; } } } if ( min == max ) { end = end - size ; } else { for ( var i = start ; i < end ; i ++ ) {hitCount [ i ] = 0 ; } para ( var i = inicio ; i < fin ; i ++ ) { interpolación [ i ] = inicio + Math.floor ( (( A [ i ] - min ) / ( máx - min ) ) * ( tamaño - 1 ) ) ; hitCount [ interpolación [ i ]] ++ ; } para ( var i = inicio ; i < fin ; i ++ ) { si ( hitCount [ i ] > 0 ) { divideSize.push ( hitCount [ i ] ) ; } } hitCount [ fin - 1 ] = fin - hitCount [ fin - 1 ]; para ( var i = fin - 1 ; i > inicio ; i-- ) { hitCount [ i - 1 ] = hitCount [ i ] - hitCount [ i - 1 ] ; } para ( var i = inicio ; i < fin ; i ++ ) { sortedArray [ hitCount [ interpolación [ i ]]] = A [ i ]; hitCount [ interpolación [ i ]] ++ ; } para ( var i = inicio ; i < fin ;; i ++ ) { A [ i ] = sortedArray [ i ]; } } } };Variantes
Ordenación de etiquetas de interpolación
La ordenación por etiquetas de interpolación es una variante recursiva de la ordenación por interpolación. Después de distribuir los datos del array en grupos mediante una función de interpolación, cada grupo ejecuta recursivamente el algoritmo original hasta que se completa la ordenación.
Para evitar el desbordamiento de pila causado por la recursión, utilice una matriz de etiquetas de tipo de datos booleano para operar la función recursiva y liberar la memoria. El espacio de memoria adicional requerido es cercano a bits. Contiene una matriz bidimensional de memoria asignada dinámicamente y una matriz de etiquetas de tipo de datos booleano. Los cubos se pueden implementar utilizando una pila, una cola, una matriz asociativa o una estructura de árbol.
Al igual que la ordenación por interpolación, la ordenación por etiquetas de interpolación se ejecuta en tiempo lineal cuando los valores en el array a ordenar están distribuidos uniformemente. El algoritmo de ordenación por cubetas no limita la ordenación al límite inferior de . La complejidad de rendimiento promedio de la ordenación por etiquetas de interpolación es .
Algoritmo de ordenación de etiquetas por interpolación
- Establece una matriz de etiquetas igual al tamaño de la matriz original e inicialízala con un valor falso.
- [Ordenación principal] Determina si se han ordenado todos los cubetas del arreglo original. Si la ordenación no se ha completado, se ejecuta la [función Dividir].
- [Función de división] Encuentra los valores máximo y mínimo en el cubo. Si el valor máximo es igual al valor mínimo, la ordenación ha finalizado y la división se detiene.
- Crea una matriz bidimensional con todos los cubos vacíos. Divide los datos en los cubos según el número de interpolación.
- Después de dividir los datos en los cubos, marca la posición inicial de cada cubo como un valor verdadero en el array de etiquetas. Luego, vuelve a colocar los elementos en el array original uno por uno, desde todos los cubos que no estén vacíos.
- Volver a [Ordenar principal].
Práctica
Código JavaScript:
Array . prototype . InterpolaionTagSort = function () { // Whale Chen acepta la "Licencia Wikipedia CC BY-SA 3.0". Fecha de firma: 2019-06-21 // var end = this . length ; if ( end > 1 ) { var start = 0 ; var Tag = new Array ( end ); // Paso 1 del algoritmo for ( var i = 0 ; i < end ; i ++ ) { Tag [ i ] = false ; } Divide ( this ); } while ( end > 1 ) { // Paso 2 del algoritmo while ( Tag [ -- start ] == false ) { } // Encuentra el inicio del siguiente cubo Divide ( this ); }función Divide ( A ) { var min = A [ inicio ]; var max = A [ inicio ]; para ( var i = inicio + 1 ; i < fin ; i ++ ) { si ( A [ i ] < min ) { min = A [ i ]; } si no { si ( A [ i ] > max ) { max = A [ i ]; } } } si ( min == max ) { fin = inicio ; } // Paso 3 del algoritmo: Comienza para ser el final del siguiente cubo si no { var interpolación = 0 ; var tamaño = fin - inicio ; var Cubo = nuevo Array ( tamaño ); // Paso 4 del algoritmo para ( var i = 0 ; i < tamaño ; i ++ ) { Cubo [ i ] = nuevo Array (); } para ( var i = inicio ; i < fin ; i ++ ) { interpolación = Math . piso ((( A [ i ] - min ) / ( max - min )) * ( tamaño - 1 )); Cubo [ interpolación ]. empujar ( A [ i ]); } para ( var i = 0 ; i< tamaño ; i ++ ) { if ( Bucket [ i ]. length > 0 ) { // Paso 5 del algoritmo Tag [ start ] = true ; for ( var j = 0 ; j < Bucket [ i ]. length ; j ++ ) { A [ start ++ ] = Bucket [ i ][ j ]; } } } } } // Paso 6 del algoritmo };Ordenación de etiquetas de interpolación in situ
El algoritmo de ordenación por interpolación in situ es una variante del algoritmo de ordenación por interpolación. Ordena series de enteros consecutivos no repetitivos. Permite la ordenación con solo N intercambios, manteniendo N etiquetas de bits, lo que ahorra tiempo y memoria. Sin embargo, el arreglo a ordenar debe ser una secuencia continua de enteros o una progresión aritmética no repetitiva.
Los datos de la columna del factor no deben repetirse. Por ejemplo, la ordenación de 0 a 100 se puede realizar en una sola pasada. El número de intercambios es: , la complejidad temporal del cálculo es: , y la complejidad espacial máxima es de bits.
Este algoritmo utiliza únicamente un array de etiquetas adicional. Este array tiene la misma longitud que el array original y es de tipo booleano. Para cada elemento no intercambiado, el algoritmo calcula una nueva posición interpolada p e intercambia los dos elementos del array. El array de etiquetas se marca como verdadero en la posición p , y el algoritmo se incrementa hasta llegar al último elemento, momento en el que el array queda ordenado.
Proceso del algoritmo:
- Establezca un número igual de matrices de etiquetas para inicializarlas con valores falsos.
- Visita el array cuando tag[i] sea falso, calcula la posición correspondiente a interpolación=p.
- Intercambia a[i] y a[p], sea tag[p] = verdadero.
- El recorrido está completo y la clasificación también.
Práctica
Código JavaScript:
Array . prototype . InPlaceTagSort = function () { // Edit Date: 2019-07-02 var n = this . length ; var Tag = new Array ( n ); for ( i = 0 ; i < n ; i ++ ) { Tag [ i ] = false ; } var min = this [ 0 ]; var max = this [ 0 ]; for ( i = 1 ; i < n ; i ++ ) { if ( this [ i ] < min ) { min = this [ i ]; } else { if ( this [ i ] > max ) { max = this [ i ]; } } } var p = 0 ; var temp = 0 ; for ( i = 0 ; i < n ; i ++ ) { while ( Tag [ i ] == false ) { p = Math . piso ((( this [ i ] - min ) / ( max - min )) * ( n - 1 )); temp = this [ i ]; this [ i ] = this [ p ]; this [ p ] = temp ; Tag [ p ] = true; } } }; necesitaSortArray . InPlaceTagSort ();Actuación
En "Análisis matemático de algoritmos", Donald Knuth comentó "... que la investigación sobre la complejidad computacional es una forma interesante de perfeccionar nuestras herramientas para los problemas más rutinarios a los que nos enfrentamos a diario". [ 3 ]
Knuth señaló además que, con respecto al problema de ordenación, la permutación in situ eficiente en tiempo está intrínsecamente ligada al problema de encontrar los líderes de ciclo, y las permutaciones in situ podrían realizarse fácilmente en tiempo si se nos permitiera manipular bits de "etiqueta" adicionales que especificaran cuánto de la permutación se ha realizado en cada momento. Sin dichos bits de etiqueta, concluye que "parece razonable conjeturar que cada algoritmo requerirá para la permutación in situ al menos pasos en promedio". [ 3 ]
El algoritmo de ordenación por interpolación in situ es uno de los algoritmos de ordenación que, según el profesor Donald Knuth, "manipula bits de "etiqueta" adicionales... encontrando los líderes del ciclo, y las permutaciones in situ podrían realizarse fácilmente en tiempo real".
Métodos de clasificación mixtos
El algoritmo de ordenación por cubetas presenta limitaciones en ciertas situaciones. Por ejemplo, si el valor máximo de un dato es mayor que N veces el siguiente valor más grande, tras el procesamiento, todos los elementos, excepto el valor máximo, caen en la misma cubeta, lo que resulta en una distribución deficiente. Una segunda pasada de ordenación, utilizando, por ejemplo, la ordenación por inserción, puede aumentar considerablemente la complejidad de la ejecución . Esto anula las ventajas y el alto rendimiento que ofrece la ordenación por cubetas.
La ordenación por interpolación es una forma de usar recursivamente la ordenación por cubetas. Después de realizar la recursión, se sigue usando la ordenación por cubetas para dispersar la serie. Esto puede evitar la situación anterior. Si se quiere que la complejidad de ejecución de la ordenación por interpolación recursiva sea baja , es necesario presentar una amplificación factorial en toda la serie. De hecho, hay muy pocas probabilidades de que se produzca una serie de distribuciones especiales.
Véase también
Referencias
- ↑ Algoritmo NIST. "ordenación por interpolación" .
Definición: Véase ordenación por histograma.
- ↑ Algoritmo NIST. "ordenación por histograma" .
Definición: Un refinamiento eficiente de 3 pasadas de un algoritmo de ordenación por cubetas.
- ^ Karl -Dietrich Neubert (1998). "El algoritmo FlashSort" . Consultado el 6 de noviembre de 2007 .
Enlaces externos
- interpolaciónOrdenar.html
- histogramaOrdenar.html
- El algoritmo FlashSort
- Análisis matemático de algoritmos
- http://www.drdobbs.com/database/the-flashsort1-algorithm/184410496
- 桶排序遞迴方式演算法 Clasificación de cubos Método recursivo. Ballena Chen 16/09/2012
- 插值標簽排序演算法 Algoritmo de clasificación de etiquetas de interpolación. Ballena Chen 24/03/2013
- Ordenación por interpolación (versión Pascal disponible)
- Plataforma de pruebas de ordenación de matrices JavaScript de w3schools
- Algoritmos de ordenación
- Tipos estables