1.hanno塔问题的递归分形图案,数的层数等于汉诺塔问题的层数,带颜色的表示真实的操作。



汉诺塔实现代码:
#include <stdio.h>
#include <stdlib.h>
void hannuo(int n, char from, char to, char mid)
{
if(n == 2)
{
printf("0: %c->%c.\n", from, to);
printf("1: %c->%c.\n", from, mid);
printf("0: %c->%c.\n", to, mid);
printf("2: %c->%c.\n", from, to);
printf("0: %c->%c.\n", mid, from);
printf("1: %c->%c.\n", mid, to);
printf("0: %c->%c.\n", from, to);
}
else
{
hannuo(n-1, from, mid, to);
printf("%d: %c->%c.\n", n, from, to);
hannuo(n-1, mid, to, from);
}
}
int main(void)
{
hannuo(3, 'A', 'B', 'C');
return 0;
}

#include <stdio.h>
#include <stdlib.h>
static int count = 0;
void hannuo(int n, char from, char to, char mid)
{
if(n == 2)
{
printf("0: %c->%c.\n", from, to);
printf("1: %c->%c.\n", from, mid);
printf("0: %c->%c.\n", to, mid);
printf("2: %c->%c.\n", from, to);
printf("0: %c->%c.\n", mid, from);
printf("1: %c->%c.\n", mid, to);
printf("0: %c->%c.\n", from, to);
count += 7;
}
else
{
hannuo(n-1, from, mid, to);
printf("%d: %c->%c.\n", n, from, to);
count ++;
hannuo(n-1, mid, to, from);
}
}
int main(void)
{
hannuo(9, 'A', 'B', 'C');
printf("total %d.\n", count);
return 0;
}
hanno塔的操作次数公式为:
也可以这样推导:
如果将n+1块塔看成二进制n+1 bit的二进制的话,则每个从LSB到MSB,依次需要移动
次,最高位只需要移动1次,和上面的图是吻合的。
所以
n为层数,从0开始,比如,如果传入参数为hannuo(9,...),则n=10,总共需要1023步移动。
或者,修改为更加优美的形式
#include <stdio.h>
#include <stdlib.h>
static int count = 0;
void hannuo(int n, char from, char to, char mid)
{
if(n == 0)
{
printf("0: %c->%c.\n", from, to);
count += 1;
}
else
{
hannuo(n-1, from, mid, to);
printf("%d: %c->%c.\n", n, from, to);
count ++;
hannuo(n-1, mid, to, from);
}
}
int main(void)
{
hannuo(9, 'A', 'B', 'C');
printf("total %d.\n", count);
return 0;
}
差异:

#include <stdio.h>
#include <stdlib.h>
static int count = 0;
void hannuo(int n, char from, char to, char mid)
{
if(n == 0)
{
printf("%d: %c->%c.\n", n, from, to);
count += 1;
}
else
{
hannuo(n-1, from, mid, to);
printf("%d: %c->%c.\n", n, from, to);
count ++;
hannuo(n-1, mid, to, from);
}
}
int main(void)
{
hannuo(9, 'A', 'B', 'C');
printf("total %d.\n", count);
return 0;
}
hanno塔的最小可处理单元是2个

睡眠递归的例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void sleepy(int n)
{
sleep(1);
if(n == 0)
printf("%s line %d.\n", __func__, __LINE__);
else
sleepy(n-1);
return;
}
int main(void)
{
sleepy(10);
return 0;
}

尾递归改为非递归:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void sleepy(int n)
{
start:
//printf("%s line %d, n = %d.\n", __func__, __LINE__, n);
sleep(1);
//printf("%s line %d, n = %d.\n", __func__, __LINE__, n);
if(n == 0) {
printf("%s line %d.\n", __func__, __LINE__);
} else {
#if 0
printf("%s line %d, n = %d.\n", __func__, __LINE__, n);
sleepy(n-1);
printf("%s line %d, n = %d.\n", __func__, __LINE__, n);
#else
printf("%s line %d, n = %d.\n", __func__, __LINE__, n);
n --;
//printf("%s line %d, n = %d.\n", __func__, __LINE__, n);
goto start;
#endif
}
return;
}
int main(void)
{
sleepy(10);
return 0;
}
update hannuo program
#include <stdio.h>
#include <stdlib.h>
static int count = 0;
void hannuo(int n, char from, char to, char by)
{
if(n == 0) {
printf("step %d, move %d: %c->%c.\n", count, n, from, to);
count += 1;
} else {
hannuo(n-1, from, by, to);
printf("step %d, move %d: %c->%c.\n", count, n, from, to);
count ++;
hannuo(n-1, by, to, from);
}
return;
}
int main(void)
{
hannuo(9, 'A', 'B', 'C');
printf("total %d.\n", count);
return 0;
}
$ grep "move 0:" a.log|wc -l
512
$ grep "move 1:" a.log|wc -l
256
$ grep "move 2:" a.log|wc -l
128
$ grep "move 3:" a.log|wc -l
64
$ grep "move 4:" a.log|wc -l
32
$ grep "move 5:" a.log|wc -l
16
$ grep "move 6:" a.log|wc -l
8
$ grep "move 7:" a.log|wc -l
4
$ grep "move 8:" a.log|wc -l
2
$ grep "move 9:" a.log|wc -l
1

从LSB到MSB,每一个BIT变换的频率依次减半,比如上图,对于四个BIT的二进制数字,其BIT0变化8次,BIT1变化4,BIT2变化2,BIT3变化1,构成15个数。

本文深入探讨了汉诺塔问题的递归解决方法,并提供了详细的C语言实现代码。通过不同版本的代码示例,展示了如何计算移动次数及优化输出格式。
3207

被折叠的 条评论
为什么被折叠?



