汉诺塔的递归和非递归实现
借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b, c),即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”),并保证每个移动符合汉诺塔问题的要求。
输入格式:
输入为一个正整数N,即起始柱上的盘数。
输出格式:
每个操作(移动)占一行,按柱1 -> 柱2
的格式输出。
输入样例:
3
输出样例:
a -> c a -> b c -> b a -> c b -> a b -> c a -> c
代码:(递归算法)
ps:函数hanoi里的n是n个盘子,move函数里的n是第n个
1 #include <stdio.h> 2 int i=1;//记录步数 3 void move(int n,char x,char y) //将编号为n的盘子由from移动到to 4 { 5 printf("将%d号盘子%c---->%c ",n,x,y); 6 } 7 void hanoi(int n,char x,char y,char z)//将n个盘子由初始塔移动到目标塔(利用借用塔) 8 { 9 if (n==1) 10 move(1,x,z);//只有一个盘子是直接将初塔上的盘子移动到目的地 11 else 12 { 13 hanoi(n-1,x,z,y);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上 14 move(n,x,z); //将剩下的一个盘子移动到目的塔上 15 hanoi(n-1,y,x,z); 16 //最后将借用塔上的n-1个盘子移动到目的塔上 17 } 18 } 19 int main() 20 { 21 printf("请输入盘子的个数: "); 22 int n; 23 scanf("%d",&n); 24 char x='A',y='B',z='C'; 25 printf("盘子移动情况如下: "); 26 hanoi(n,x,y,z); 27 return 0; 28 }
递归的算法,简洁一点也可以这样写:
void Hanoi(int n,char A,char B,char C) //A借助B,将n个盘子移到C ,递归的妙用在于不用关心具体实现的细节 { if (n==1)printf("%c -> %c",A,C); //只有一个盘子,直接将其移到C else { Hanoi(n-1,A,C,B); //第一步,A借助C,将n-1个盘子移到B; printf("%c -> %c",A,C); //第二步,将A上剩余的一个盘移到C; Hanoi(n-1,B,A,C) //第三步,将B上的n-1个盘子移到C。 } }
坦白说,关于非递归的算法,没什么思路,就是用递归算法跑一些数值,想出来的算法也不是特别好
代码:(非递归算法)
1 #include<iostream> 2 #include<algorithm> 3 #include <stack> 4 #include <cstdio> 5 #include<cmath> 6 using namespace std; 7 int temp1=-1, temp2=-1; 8 char s[4] = { 'q','a','b','c' };//为了解题简便,我是从1开始算的 9 stack<int> a[4]; 10 int c1 = 0; 11 int rank1[4]; 12 bool compare(int a1,int b1) 13 { //给栈顶元素排序用 14 if (a[a1].top() >= a[b1].top()) 15 return true; 16 if (a[a1].top() < a[b1].top()) 17 return false; 18 return false; 19 } 20 bool move1(int before,int after) { //移动物块 21 if ((a[after].top() - a[before].top())%2==0) 22 return false; 23 a[after].push(a[before].top()); 24 a[before].pop(); 25 temp1 = before; temp2 = after; //记录上一次移动的物块位置 26 printf("%c -> %c ",s[temp1],s[temp2]); 27 c1++; 28 return true; 29 } 30 int main(){ 31 int i, N; 32 cin >> N;//起始柱上的盘数 33 a[1].push(N+1);//保证栈不会为空 34 for (i = 0; i < N; i++) 35 a[1].push(N-i); //初始化 36 a[2].push(N + 2); 37 a[3].push(N+3); 38 if (N % 2 == 1) { //N为奇数还是偶数,第一次移物块到哪里是不同的 39 move1(1, 3); 40 temp1 = 1; 41 temp2 = 3; 42 } 43 else { 44 move1(1, 2); 45 temp1 = 1; temp2 = 2; 46 } 47 for (i = 1; i <= 3; i++)//初始化栈排序表 48 rank1[i] = i; 49 int tt; 50 while (c1 < pow(2, N) -1) { 51 sort(rank1 + 1, rank1 + 4, compare);//按compare函数排序 52 if (temp2 == rank1[2]) { //刚移动过的物块不会再被移动 53 if(tt==temp1) //别问我为什么,找规律找出来的 54 move1(rank1[3], rank1[2]); 55 else 56 move1(rank1[3], rank1[1]); 57 } 58 else 59 move1(rank1[2], rank1[1]); 60 tt = rank1[2]; 61 } 62 }