0
点赞
收藏
分享

微信扫一扫

上机回顾day3

E_topia 2022-04-01 阅读 79
c语言

汉诺塔递归与非递归的实现

问题描述:
汉诺塔问题源自印度一个古老的传说,印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱,其中的一根柱子上按照从小到大的顺序摞着 64 个黄金圆盘。梵天命令一个叫婆罗门的门徒将所有的圆盘移动到另一个柱子上,移动过程中必须遵守以下规则:
1、每次只能移动柱子最顶端的一个圆盘;
2、每个柱子上,小圆盘永远要位于大圆盘之上;
在这里插入图片描述

输入:一个正整数N,为起始柱上的盘数。
输出:每一步移动操作(%c -> %c格式输出)。
算法优化:无。
递归算法思路:

(1)先将 n - 1 个盘子从 a 通过 c 移动到 b 。

(2)再将最后一个盘子从 a 移动到 c 。

(3)最后将 n - 1 个盘子从 b 通过 a 移动到 c 。

#include <stdio.h>
void hanoi(int num, char sou, char tar,char aux) {
    //统计移动次数
    static int i = 1;
    //如果圆盘数量仅有 1 个,则直接从起始柱移动到目标柱
    if (num == 1) {
        printf("%c -> %c\n", sou, tar);
        i++;
    }
    else {
        //递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上
        hanoi(num - 1, sou, aux, tar);
        //将起始柱上剩余的最后一个大圆盘移动到目标柱上
        printf("%c -> %c\n", sou, tar);
        i++;
        //递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上
        hanoi(num - 1, aux, tar, sou);
    }
}

int main()
{
    //以移动 N 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示
    int n;
    scanf("%d", &n);
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

输入:

3

输出:

在这里插入图片描述

非递归算法思路:
1.将n-1个盘子由a柱借助c柱移动到b柱
2.将最下面的盘子由a柱直接移动到c柱
3.将那n-1个盘子在由b柱借助a柱移动到c柱

因为这个是出栈时的操作,所以入栈时要到着写

#include<stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef struct{
     int N;
     char A;        //起始柱
     char B;        //借助柱
     char C;        //目标柱
}ElementType;
typedef struct {
    ElementType Data[MaxSize];
    int top;
}Stack;//汉诺塔问题的结构类型
void Push(Stack *PtrS, ElementType item){
     //入栈操作
     if (PtrS->top == MaxSize)
     {
         printf("The stack is full!\n");
         return;
     }
     else
     {
         PtrS->Data[++(PtrS->top)] = item;
         return;
     }
}
ElementType Pop(Stack *PtrS){
    if (PtrS->top == -1)
      {
          printf("The stack is empty!\n");
          exit(1);   //直接终止程序,一般不会出现这个错误
      }
      else
      {
          PtrS->top--;
         return (PtrS->Data[PtrS->top + 1]);        //或者是return PtrS->Data[PtrS->top--];
      }
}
//借助栈的非递归实现
 void Hanoi(int n){
    ElementType P, toPush;
    Stack S;
     
    P.N = n; P.A = 'a'; P.B = 'b'; P.C = 'c';
    S.top = -1;

     Push(&S, P);
     while (S.top != -1)        //当堆栈不为空时
     {
         P = Pop(&S);//出栈
         if (P.N == 1)//当只剩一个盘子时,直接由当前柱移动到目的柱
             printf("%c -> %c\n", P.A, P.C);
         else
         {
             toPush.N = P.N - 1;
             toPush.A = P.B; toPush.B = P.A; toPush.C = P.C;
             Push(&S, toPush);        //将第三步(n - 1, b, a, c)入栈
             toPush.N = 1;
             toPush.A = P.A; toPush.B = P.B; toPush.C = P.C;
             Push(&S, toPush);        //将第二步1, a, b, c)入栈
             toPush.N = P.N - 1;
             toPush.A = P.A; toPush.B = P.C; toPush.C = P.B;
             Push(&S, toPush);        //将第一步(n - 1, a, c, b)入栈
         }
     }
 }
int main(){
    int n;
    scanf("%d", &n);
    if (n <= 0)return 0;
    else Hanoi(n);
}

输入:

3

输出:
在这里插入图片描述
总结:
汉诺塔其实是一个简单的递归问题,让我们更加深刻的了解递归的应用。但是如果采用非递归去实现就会考查到堆栈的运用,这样反而弄得更加的复杂化。

举报

相关推荐

Day3

Python Day3

QT DAY3

Qt(day3)

Leetcode Day3

PAT DAY3

JS DAY3

【C语言】day3

0 条评论