首页 > 其他分享 >代码4:非递归的汉诺塔

代码4:非递归的汉诺塔

时间:2024-07-07 16:10:32浏览次数:1  
标签:via 递归 代码 hanoi char pc 汉诺塔 Frame

Intro:

  • 绪论2:应用视角的操作系统。
  • 目的:改写为非递归的汉诺塔,理解“状态机模型”。

一、递归版汉诺塔

课本上最基础的做法,递归是模拟某一步:把n-1个盘子从from移到via,就能把剩下的一个盘子从from移到to,最后把n-1个盘子从via移到to即可。

void hanoi_r(int n, char from, char to, char via) {
  if (n == 1) {
    printf("%c -> %c\n", from, to);
  } else {
    hanoi_r(n - 1, from, via, to);
    hanoi_r(1,     from, to,  via);
    hanoi_r(n - 1, via,  to,  from);
  }
}

二、非递归版

非递归版的实现用了栈 Frame[64] 模拟整个调用过程。

typedef struct {
  int pc, n; // 当前计数器、盘子数
  char from, to, via;
} Frame;

// ...和__VA_ARGS__为可变参数列表,具体语法过程为:
// 1. {.pc ...} 代表 struct Frame 的初始化
// 2. 栈顶指针 top 下移,模拟把初始化好的 Frame 压入栈中
#define call(...) ({ *(++top) = (Frame) { .pc = 0, __VA_ARGS__ }; })
#define ret()     ({ top--; }) // 出栈
#define goto(loc) ({ f->pc = (loc) - 1; }) // f->pc 代表了具体执行 swtich 中哪条指令

void hanoi_nr(int n, char from, char to, char via) {
  Frame stk[64], *top = stk - 1;
  call(n, from, to, via); // 初始化
  for (Frame *f; (f = top) >= stk; f->pc++) {
    n = f->n; from = f->from; to = f->to; via = f->via;
    switch (f->pc) {
      case 0: if (n == 1) { printf("%c -> %c\n", from, to); goto(4); } break;
      case 1: call(n - 1, from, via, to);   break;
      case 2: call(    1, from, to,  via);  break;
      case 3: call(n - 1, via,  to,  from); break;
      case 4: ret();                        break;
      default: assert(0);
    }
  }
}

这段代码的执行过程需要多读两遍。

标签:via,递归,代码,hanoi,char,pc,汉诺塔,Frame
From: https://www.cnblogs.com/7ytr5/p/18282287

相关文章

  • MATLAB算法实战应用案例精讲-【数模应用】偏最小二乘回归分析(PLS)(附MATLAB和python代码
    目录前言知识储备回归的方法回归的检验算法原理数学模型偏最小二乘回归建模原理:PLS的准则函数偏最小二乘基本算法​编辑 ​编辑PLS回归模型算法思想PLS回归与MLS、PCR、MRA比较SPSSAU案例应用其他说明SPSS示例(PLS命令) 变量列表(PLS命令) MODEL......
  • 图神经网络版本的Kolmogorov Arnold(KAN)代码实现和效果对比
    MLP是多层感知器(MultilayerPerceptron)的缩写,它是一种前馈人工神经网络。MLP由至少三层节点组成:一个输入层、一个或多个隐藏层以及一个输出层。每一层的节点都与下一层的每个节点相连,并且每个连接都有一个权重。MLP通过这些权重和节点的激活函数来学习输入数据的模式。Kolmogorov......
  • DDPM生成人脸代码
    基于DDPM介绍的理论,简单实现DDPM生成人脸,代码如下:utils.pyimportosfromtorch.utils.dataimportDatasetfromtorchvision.transformsimporttransformsimportglobimportcv2classMyDataset(Dataset):def__init__(self,img_path,device):super(My......
  • let 声明的变量,只在代码块内有效
    {leta=10;varb=1;}a//ReferenceError:aisnotdefinedb//1for循环的计数器,就很适合使用let命令。for(leti=0;i<10;i++){//...}console.log(i);//ReferenceError:iisnotdefined上面代码中,计数器i只在for循环体内......
  • 代码的坏味道——长参数
        前言:一个函数的参数越少越好,并不是参数少或不传更优雅,而是有其他方案来优化长参数。一个函数的参数尽量不要超过3个,如果超过了这个限制,那么代码的坏味道就产生了。一、整合参数如果参数很多,那么第一就要考虑,这些参数是否存在关联?若存在是否可以归为一组?badCase:......
  • 微信小程序-首页制作 - (图解+代码流程)
    目录首页制作效果图一、轮播图的制作1.首页轮播图.wxml代码2.swiper和swiper-item组件二、滑动视图效果图1.首页滑动视图.wxml代码scroll-view组件2.首页滑动视图.wxss代码white-space:nowrap;三、标题和学员作品图片布局效果图1.标题和作品图片.wxml代......
  • 使用zdppy_api+onlyoffice word文档在线共同编辑,附完整的vue3前端代码和python后端代
    参考文档:https://api.onlyoffice.com/zh/editors/basichttps://api.onlyoffice.com/zh/editors/coedit基本的架构思考:文档表:记录的是文档信息key:这个key可以标识唯一的一个文档,可以是文档的hash值fileType:文档的类型,docx,txt,pdf,其他title:文档的标题,也就是文档的实际......
  • 轻松解决win7和win10共享打印机出现错误代码0x00000709的办法
    轻松解决win7系统共享打印机错误代码0x00000709的办法轻松解决win10系统共享打印机错误代码0x00000709的办法为了方便用户更方便充分的利用打印机,配置打印机共享功能,开启共享后可以查询到共享的打印机,但是点击选择连接时出现错误代码0x00000709,尝试了各种方法修改注册表等还......
  • Java毕设项目汇总 - 1 - springboot框架+vue+源代码+论文等完整资料
    逃逸的卡路里博主介绍:✌️码农一枚|毕设布道师,专注于大学生项目实战开发、讲解和毕业......
  • stm32串口 环形缓冲区 代码
    voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){ //printf("ITIN\r\n");// printf("%d\r\n",HAL_GetTick()); //置零设定电流值PID时间if(huart->Instance==USART3){ //将数据放入缓冲区 circular_buffer.buffe......