Red de conocimiento informático - Conocimiento sistemático - Informe de programación de ensamblaje de Hannota

Informe de programación de ensamblaje de Hannota

Notas de estudio de STL: utilice métodos no recursivos para resolver el problema de la Torre de Hannover

Notas de estudio de STL: utilice métodos no recursivos para resolver el problema de la Torre de Hannover

shaohui_1983#163. com t,srctop,dsttop, britop,last = 0;

7 pila<.int> ssrc,sdst,sbri;

8 para (cnt=1;cnt<=escala ; cnt++)

9 ssrc.push(cnt);

10

11 mientras (sdst.size() != escala)

12 {

13 srctop = ssrc.empty() ?0 : ssrc.top();

14 dsttop = sdst.empty() ?0 : sdst.top( );

15 britop = sbri.empty() ?0 : sbri.top();

16

17 if (último ! = srctop && ( (srctop%2 && srctop> dsttop) || ((srctop%2==0) && srctop>britop)))

18 {

19 ssrc.pop();

20 último = srctop;

21 srctop % 2 ?push(srctop);

22 si (srctop % 2)

23 cout< < "mover disco "<

24 else

25 cout< < "mover disco "<

26 }

27

28 if (último != britop && ((britop%2 && britop>srctop) || ((britop%2==0) && britop>dsttop)))

29 {

30 sbri.pop();

31 último = britop;

32 britop % 2 ? .push(britop) : sdst .push(britop);

33

34 if (britop % 2)

35 cout<< "mover disco" <

36 else

37 cout<< "mover disco " <

38 }

39

40 si (último ! = dsttop && ((dsttop%2

&& dsttop>britop) || ((dsttop%2==0) && dsttop>srctop)))

41 {

42 sdst.pop();

43 último = dsttop;

44 dsttop % 2 ?sbri.push(dsttop) : ssrc.push(dsttop);

45 si (dsttop % 2)

46 cout<< "mover disco "<

47 else

48 cout<< "mover disco "<

49 }

50 }

51 }

El código anterior parece ser más complicado, pero es principalmente la complejidad de las condiciones lo que hace que este código difícil de entender. Hay tres declaraciones if en el bucle while, que se utilizan para determinar si el disco actual se puede mover. Si es así, muévalo e imprímalo.

Para mover un disco se deben cumplir las siguientes dos condiciones

1. No debe haber sido movido antes, es decir, no debe ser igual al último

2. El número de la letra de la unidad debe ser mayor que el número de la letra de la unidad superior en la letra de la unidad de destino.

Estas dos condiciones deben cumplirse para poder moverse, lo que prueba que existe una letra de unidad única que se puede mover en cualquier momento dado. .

Para facilitar la comparación con el método inicial, se debe convertir el número de placas al generar, o se debe utilizar el método de reducirlo al número original. Es decir, el pequeño está arriba y el grande abajo. Lo que escribí arriba realmente no es muy conciso. Espero que haya algo mejor escrito para reemplazarlo.

3. Método recursivo

Aunque hay métodos recursivos en el libro, todavía uso mi método recursivo como referencia. Luego utilícelo para comparar el rendimiento.

3 #define mover(disco,src,dst) cout<< "mover disco"<

4 void hanoi_r(int size,char src,char dst,char bri)

5 {

6 if (size == 1)

7 mover(tamaño,src,dst);

8 más

9 {

10 hanoi_r(tamaño-1,src, bri,dst);

11 movimiento(tamaño,src,dst);

12 hanoi_r(tamaño-1,bri,dst,src);

13 }

14 }

4. Comparación de métodos

Debido a que existen diferentes implementaciones, por supuesto que tenemos que compararlas. Siempre pensé que los métodos no recursivos son más rápidos que los métodos no recursivos. métodos recursivos, pero resultó que este no era el caso.

Dado que la impresión tomó menos tiempo que la implementación, lo eliminé y solo modifiqué las macros que definí

Pila

. p>

#define print_oprt(op)

Recursivo

#define move(disk,src,dst)

Esto significa que la operación de impresión no nada.

Aquí hay una comparación del tiempo (en segundos) que me tomó resolver el problema de Hannuka usando 3 métodos diferentes en un entorno virtual Linux en mi computadora, en una escala de tiempo de 1-30, puedes También descarga este programa a tu computadora y pruébalo.

Tick stack recursivo otro (1-30)

1 0 0 0

2 0 0 0

3 0 0 0

4 0 0 0

5 0 0 0

6 0 0 0

7 0 00

8 0 0 0

9 0 0 0

10 0 0 0

11 0 0 0

12 0 0 0

13 0 0 0

14 0 0 0.01

15 0 0 0.01

16 0.02 0 0.01

17 0.03 0 0,03

18 0,05 0 0,05

19 0,12 0 0,12

20 0,23 0,01 0,23

21 0,49 0,01 0,47

22 0,95 0,04 0,89

23 1,92 0,07 1,87

24 3,8 0,15 3,55

25 7,65 0,3 7,52

26 15,2 0,6 14,24

27 30,49 1,2 29,7

28 61,11 2,41 57,24

29 111,15 4,29 97,56

30 201,09 7,72 184,32

El tiempo que lleva usar la pila y otros métodos es relativamente cercano, mientras que el uso de la recursividad es el más rápido. La brecha entre los dos es muy grande. ¿Por qué? No debería haber una diferencia tan grande.

En resumen, pueden existir las siguientes razones:

1. STL en sí no es muy eficiente

STL es poderoso y su eficiencia inevitablemente se verá afectada.

2. Hay menos funciones llamadas de forma recursiva, que es la llamada en sí, mientras que hay más funciones llamadas de otras formas.

Del código, podemos ver que hay menos funciones. llamado de forma no recursiva, que es la llamada en sí, mientras que otros métodos llaman más funciones

Del código, podemos ver que la cantidad de funciones llamadas en el método no recursivo es mucho mayor que en el método recursivo Se llaman varias funciones para cada operación de movimiento: pop, push, etc. En el modo recursivo, cada operación de movimiento solo se llama a sí misma una vez, por lo que la carga sobre la pila del sistema es mucho menor.

3. La implementación de la pila implica la construcción y destrucción de múltiples objetos, así como múltiples reasignaciones de la pila, lo que también lleva mucho tiempo (la pila STL es una estructura de almacenamiento secuencial, cuando el espacio Si no es suficiente, solicite doble espacio del sistema)

Apéndice

Apéndice

He comprimido todos los códigos mencionados anteriormente y los descargué.

/zhengsh/download/hanoi.tar.gz

Hay instrucciones más detalladas en el archivo Léame. A excepción de hanoi_cmp.c, se pueden compilar otros archivos en Windows y Linux. Estoy usando la implementación de Linux, por lo que es mejor volver a compilarlos en Linux.