El algoritmo del montón genera todas las permutaciones posibles de n objetos. BR Heap lo propuso por primera vez en 1963. [1] El algoritmo minimiza el movimiento: genera cada permutación de la anterior mediante el intercambio de un solo par de elementos; los otros elementos n −2 no se alteran. En una revisión de 1977 de los algoritmos de generación de permutación, Robert Sedgewick concluyó que en ese momento era el algoritmo más efectivo para generar permutaciones por computadora. [2]
La secuencia de permutaciones de n objetos generados por el algoritmo de Heap es el comienzo de la secuencia de permutaciones de n +1 objetos. Entonces, hay una secuencia infinita de permutaciones generadas por el algoritmo de Heap (secuencia A280318 en el OEIS ).
Detalles del algoritmo [ editar ]
Para una colección que contiene n elementos diferentes, Heap encontró un método sistemático para elegir en cada paso un par de elementos para cambiar a fin de producir cada permutación posible de estos elementos exactamente una vez.
Descrito recursivamente como un método de disminución y conquista , el algoritmo de Heap opera en cada paso delElementos iniciales de la colección. Inicialmente y posteriormente . Cada paso genera el permutaciones que terminan con el mismo elementos finales Hace esto llamándose una vez con el elemento inalterado y luego veces con el () elemento intercambiado para cada una de las iniciales elementos. Las llamadas recursivas modifican la inicialse necesitan elementos y una regla en cada iteración para seleccionar cuál se intercambiará con la última. El método del montón dice que esta elección se puede hacer por la paridad del número de elementos operados en este paso. Sies par, entonces el elemento final se intercambia iterativamente con cada índice de elemento. Si es extraño, el elemento final siempre se intercambia con el primero.
También se puede escribir el algoritmo en un formato no recursivo. [3]
Prueba [ editar ]
En esta prueba, usaremos la implementación a continuación como Algoritmo de Heap. Si bien no es óptimo (consulte la sección a continuación), la implementación sigue siendo correcta y producirá todas las permutaciones. La razón para usar la siguiente implementación es que el análisis es más fácil y ciertos patrones pueden ilustrarse fácilmente.
Reclamación: Si matriz A tiene una longitud n , a continuación, realizar el algoritmo de Heap o bien resultar en un ser "girada" a la derecha en 1 (es decir, cada elemento se desplaza a la derecha con el último elemento que ocupa la primera posición) o resultar en un ser inalterado, dependiendo de si n es par o impar, respectivamente.
Base: la afirmación anterior es trivialmente válida para ya que el algoritmo de Heap simplemente devolverá A sin modificaciones en orden.
Inducción: suponga que la afirmación es cierta para algunos . Luego tendremos que manejar dos casos para: es par o impar
Si, para A ,es incluso, entonces el subconjunto de los primeros elementos i permanecerá inalterado después de realizar el Algoritmo de Heap en la submatriz, como se supone por la hipótesis de inducción. Al realizar el Algoritmo de Heap en la submatriz y luego realizar la operación de intercambio, en la iteración k del bucle for, donde, el elemento k th en A se cambiará a la última posición de A, que puede considerarse como una especie de "buffer". Al intercambiar el primer y último elemento, luego el segundo y el último, hasta que se intercambien los elementos n y último, la matriz experimentará finalmente una rotación. Para ilustrar lo anterior, mire a continuación el caso
Si, para A ,es extraño, entonces el subconjunto de los primeros elementos i se rotará después de realizar el algoritmo de Heap en los primeros elementos i . Observe que, después de 1 iteración del ciclo for, cuando realiza el algoritmo de Heap en A , A gira a la derecha en 1. Según la hipótesis de inducción, se supone que los primeros elementos i rotarán. Después de esta rotación, el primer elemento de A se intercambiará en el búfer que, cuando se combina con la operación de rotación anterior, esencialmente realizará una rotación en la matriz. Realice esta operación de rotación n veces, y la matriz volverá a su estado original. Esto se ilustra a continuación para el caso.
La prueba de inducción para la reclamación se ha completado, que ahora llevará a qué algoritmo de Montón crea todas las permutaciones de la matriz A . Una vez más, probaremos por inducción la corrección del algoritmo de Heap.
Base: Algoritmo de Heap permuta trivialmente una matriz A de tamaño 1 como outputing A es el único y permutación de A .
Inducción: suponga que el algoritmo de Heap permuta una matriz de tamaño i . Usando los resultados de la prueba anterior, se notará que cada elemento de A estará en el "búfer" una vez cuando los primeros elementos i estén permutados. Debido a que se pueden realizar permutaciones de una matriz alterando alguna matriz A a través de la eliminación de un elemento x de A y luego agregando x a cada permutación de la matriz alterada, se deduce que el Algoritmo de Heap permuta una matriz de tamaño, porque el "búfer" en esencia contiene el elemento eliminado, que se agrega a las permutaciones del subconjunto de tamaño i . Debido a que cada iteración del Algoritmo de Heap tiene un elemento diferente de A que ocupa el búfer cuando se permuta la submatriz, cada permutación se genera ya que cada elemento de A tiene la posibilidad de agregarse a las permutaciones de la matriz A sin el elemento de búfer.
Implementaciones erróneas frecuentes [ editar ]
Es tentador simplificar la versión recursiva dada anteriormente al reducir las instancias de llamadas recursivas. Por ejemplo, como:
Esta implementación tendrá éxito en producir todas las permutaciones, pero no minimiza el movimiento. A medida que las pilas de llamadas recursivas se desenrollan, se producen intercambios adicionales en cada nivel. La mitad de estos serán no-ops de y dónde pero cuando es extraño, da como resultado intercambios adicionales de con el elemento.
permutas | adicional = intercambios | ||
---|---|---|---|
1 | 0 0 | 0 0 | 0 0 |
2 | 1 | 1 | 0 0 |
3 | 5 5 | 6 6 | 1 |
4 4 | 23 | 27 | 4 4 |
5 5 | 119 | 140 | 21 |
6 6 | 719 | 845 | 126 |
7 7 | 5039 | 5922 | 883 |
8 | 40319 | 47383 | 7064 |
9 9 | 362879 | 426456 | 63577 |
Estos intercambios adicionales alteran significativamente el orden de elementos de prefijo
Los intercambios adicionales se pueden evitar agregando una llamada recursiva adicional antes del bucle y bucle veces (como arriba) o bucle veces y comprobando que es menos que como en:
La elección es principalmente estética, pero la última da como resultado la comprobación del valor de el doble de seguido.
No hay comentarios:
Publicar un comentario