第 3 章 栈和队列(汉诺塔问题递归解法)

news2024/11/17 23:26:28

1. 背景说明

假设有 3 个分别命名为 X、Y 和 Z 的塔座,在塔座 X 上插有 n 个直径大小各不相同、依小到大编号为 1, 2,…,n 的圆盘。

现要求将 X 轴上的 n 个圆盘移至塔座 Z 上并仍按同样顺序叠排,圆盘移动时必须遵循下列规则:
(1) 每次只能移动一个圆盘;
(2) 圆盘可以插在 X、Y 和 Z 中的任一塔座上;
(3) 任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

2. 示例代码

1)hanoi.h

/* 汉诺塔定义头文件 */

#ifndef HANOI_H
#define HANOI_H

#define N 4				/* 初始汉诺塔层数 */
#define SIZE 3			/* 塔基个数 */

typedef struct {
	int **plates;
	int high[3];
} Tower;

void Init(int n, Tower *T);

void DestroyHanoi(Tower *T);

void PrintGraph(char t1, int n, char t2, Tower *T);

/* 算法 3.5, 将塔座 x 上按直径由小到大且自上而下编号为 1 至 n 的 n 个圆盘
   按规则搬到塔座 z 上。y 可用作辅助塔座 */
void Hanoi(int n, char x, char y, char z, Tower *T, int *step);

#endif // !HANOI_H

2) hanoi.c

/* 汉诺塔实现源文件 */

#include "hanoi.h"
#include <stdlib.h>
#include <stdio.h>

void Init(int n, Tower *T)
{
	/* Apply for a memory to storage the pointer of int */
	T->plates = (int **)malloc(SIZE * sizeof(int *));
	/* Apply for a memory to storage the information of the blocks */
	for (int i = 0; i < SIZE; ++i) {
		T->plates[i] = (int*)malloc(n * sizeof(int));
	}
	
	/* Initial the plate information */
	T->high[0] = n;
	T->high[1] = 0;
	T->high[2] = 0;
	for (int i = 0; i < n; ++i) {
		T->plates[0][i] = n - i;
		T->plates[1][i] = 0;
		T->plates[2][i] = 0;
	}
}

void DestroyHanoi(Tower *T)
{
	for (int i = 0; i < SIZE; ++i) {
		free(T->plates[i]);
	}

	free(T->plates);
}

/* Show move n th block from plate t1 to plate t2 */
void PrintGraph(char t1, int n, char t2, Tower *T)
{
	/* Check the parameters */
	if ((t1 == t2) && (t1 != '\0')) {
		printf("Error: Can not move block for the same plate to the same plate.\n");
		return;
	}

	/* Move from */
	if (t1 == 'x') {
		T->plates[0][T->high[0] - 1] = 0;
		--T->high[0];
	}
	else if (t1 == 'y') {
		T->plates[1][T->high[1] - 1] = 0;
		--T->high[1];
	}
	else if (t1 == 'z') {
		T->plates[2][T->high[2] - 1] = 0;
		--T->high[2];
	}

	/* Move to */
	if (t2 == 'x') {
		T->plates[0][T->high[0]] = n;
		++T->high[0];
	}
	else if (t2 == 'y') {
		T->plates[1][T->high[1]] = n;
		++T->high[1];
	}
	else if (t2 == 'z') {
		T->plates[2][T->high[2]] = n;
		++T->high[2];
	}

	/* Initialize the block string graphic */
	char **s = (char **)malloc((N + 2) * sizeof(char *));
	for (int i = 0, j; i < N + 2; ++i) {
		s[i] = (char *)malloc((N + 1) * sizeof(char));
		for (j = 0; j < i; ++j) {
			if (i == N + 1) {
				s[i][j] = '-';
			}
			else {
				s[i][j] = '*';
			}
		}
		
		if (i == N + 1) {
			s[i][j - 1] = '\0';
		}
		else {
			s[i][j] = '\0';
		}
	}

	// Eg: N = 2
	// s[0][0] = '\0'
	// s[1][0] = '*', s[1][1] = '\0'
	// s[2][0] = '*', s[2][1] = '*', s[2][2] = '\0'
	// s[3][0] = '-', s[3][1] = '-', s[3][2] = '-', s[3][2] = '\0'
	for (int i = N - 1; i >= 0; --i) {
		printf("%-*s|%-*s|%-*s\n", N, s[T->plates[0][i]], N, s[T->plates[1][i]], N, s[T->plates[2][i]]);
	}

	printf("%-*s+%-*s+%-*s\n", N, s[N + 1], N, s[N + 1], N, s[N + 1]);
	printf("%-*s%-*s%-*s\n", N + 2, "x", N + 2, "y", N + 2, "z");   /* use "" not the '' */
	
	for (int i = 0; i < N + 2; ++i) {
		free(s[i]);
	}

	free(s);
}

static void Move(char x, int n, char z, Tower *T, int *step)
{
	/* If use (*step)++, do not forget add() cause the priority of the ++ is higher than *
	   You can also not add the() instead use ++*step, no problem but bad reading */
	++(*step);
	printf("The step %2d: Move %dth block from %c to %c\n\n", *step, n, x, z);
	PrintGraph(x, n, z, T);
	printf("\n");
}

/* 算法 3.5, 将塔座 x 上按直径由小到大且自上而下编号为 1 至 n 的 n 个圆盘
   按规则搬到塔座 z 上。y 可用作辅助塔座 */
void Hanoi(int n, char x, char y, char z, Tower *T, int *step)
{
	if (n == 1) {
		Move(x, 1, z, T, step);
	}
	else {
		Hanoi(n - 1, x, z, y, T, step);
		Move(x, n, z, T, step);
		Hanoi(n - 1, y, x, z, T, step);
	}
}

3) main.c

/* 汉诺塔主函数源文件 */
/* Note: Consider use stack to storage the information of the hanoi tower */

#include "hanoi.h"
#include <stdio.h>

int main(void)
{
	char x = 'x', y = 'y', z = 'z';
	printf("Initialize the %d layers hanoi tower:\n\n", N);
	Tower T = { 0 };
	Init(N, &T);
	PrintGraph('\0', 0, '\0', &T);
	printf("\n");
	int step = 0;
	Hanoi(N, x, y, z, &T, &step);
	DestroyHanoi(&T);

	return 0;
}

3. 输出示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/984715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

伦敦金的走势高低的规律

伦敦金市场是一个流动性很强的市场&#xff0c;其价格走势会在诸多因素的影响下&#xff0c;出现反复的上下波动&#xff0c;如果投资者能够在这些高低走势中找到一定的规律&#xff0c;在相对有利的时机入场和离场&#xff0c;就能够通过不断的交易&#xff0c;累积大量的财富…

浏览器渲染原理及流程

浏览器主要组成与浏览器线程 浏览器组件 浏览器大体上由以下几个组件组成&#xff0c;各个浏览器可能有一点不同。 界面控件 – 包括地址栏&#xff0c;前进后退&#xff0c;书签菜单等窗口上除了网页显示区域以外的部分浏览器引擎 – 查询与操作渲染引擎的接口渲染引擎 – …

记录vite下使用require报错和解决办法

前情提要 我们现在项目用的是vite4react18开发的项目、但是最近公司有个睿智的人让我把webpack中的bpmn组件迁移过来、结果就出现问题啦&#xff1a;因为webpack是commonjs规范、但是vite不是、好像是es吧、可想而知各种报错 废话不多说啦 直接上代码&#xff1a; 注释是之前c…

生成式AI爆发,安全问题如何解决?

在生成式AI浪潮下&#xff0c;如何为行业用户提供符合实际应用场景需求的生成式AI服务&#xff0c;是行业数字化转型的下一个重点。《亚马逊云科技AIGC加速企业创新指南》白皮书指出&#xff0c;AIGC在游戏、零售电商、金融、媒体娱乐、医疗健康等行业都有典型应用场景。作为 A…

冠达管理:股票退市整理期?

近些年来&#xff0c;随着我国股市的发展&#xff0c;股票市场的出资者逐渐增多。但在出资过程中&#xff0c;退市股票的问题也成为了备受重视的论题。那么&#xff0c;股票退市收拾期到底是什么&#xff1f;如何应对退市股票&#xff1f; 首要&#xff0c;什么是股票退市收拾…

设备管理系统有什么功能?它有什么用?

设备管理系统已成为现代化大规模研究所&#xff0c;信息化管理体系建设中最为关键的要素。随着工业设备的机械化、自动化、大型化、高速化以及复杂化等因素不断叠加&#xff0c;设备设施对于工业生产的作用和影响越来越大&#xff0c;其各项制度和流程也涉及面广、内容繁杂。  …

中企绕道突破封锁,防不胜防 | 百能云芯

韩国的财经媒体Business Korea最新报道指出&#xff0c;尽管美方在《通胀削减法案》&#xff08;IRA&#xff09;的补贴中排除了中国&#xff0c;但中国企业正通过多种方式积极应对美国在半导体和电动汽车电池领域的封锁&#xff0c;这包括建立合资企业、设立生产基地以及开展技…

STDF-Viewer 解析工具说明

一、简介 1. 概述 STDF&#xff08;Standard Test Data Format&#xff09;&#xff08;标准测试数据格式&#xff09;是半导体测试行业的最主要的数据格式&#xff0c;包含了summary信息和所有测试项的测试结果&#xff1b;是半导体行业芯片测试数据的存储规范。 在半导体行业…

城市排水监测方案(dtu终端配合工业路由器精准监测)

台风季节,暴雨容易导致城市内涝积水。为有效监测排水状况,预警和防控积水灾害,星创易联推出智慧排水监测解决方案。 解决方案采用星创易联DTU300作为水位数据采集终端,它可挂载在河道及排水井等地点,实时监测水位变化,一旦超过预警阈值,立即通过4G网络传输报警信息,实现对水位…

使用Kmeans进行图像聚类

Kmeans可以用于与发现聚类相关的其他任务 介绍 聚类是一种无监督机器学习技术。这意味着您的数据集没有标签&#xff0c;即与解释变量发现的模式关联的目标变量。 无监督学习是找到看似相似的模式并将它们放入同一个桶中的过程。 最常用的无监督学习算法之一是Kmeans&#xff…

冠达管理:紧盯必要性 追问合理性 再融资问询透露监管新动向

在“活泼资本市场&#xff0c;提振出资者决心”一系列办法落地之后&#xff0c;再融资市场整体已明确收紧&#xff0c;但审阅尺度、相关细则还有待进一步观察。有接受采访的投行人士指出&#xff0c;现在存量项目仍在持续推进&#xff0c;监管审阅要点已在问询环节有较为充沛的…

2.7 PE结构:重定位表详细解析

重定位表&#xff08;Relocation Table&#xff09;是Windows PE可执行文件中的一部分&#xff0c;主要记录了与地址相关的信息&#xff0c;它在程序加载和运行时被用来修改程序代码中的地址的值&#xff0c;因为程序在不同的内存地址中加载时&#xff0c;程序中使用到的地址也…

单月打造8个10w+,情感类视频号如何爆火?

上月&#xff0c;腾讯公布了2023年Q2财报&#xff0c;其中&#xff0c;较为亮眼的是微信视频号的广告收入。据财报显示&#xff0c;二季度视频号用户使用时长与去年同期相比几乎翻倍&#xff0c;广告收入超过30亿元。作为微信生态的核心组件&#xff0c;视频号的内容生态呈现出…

C/C++浮点数向零舍入 2019年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C浮点数向零舍入 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 C/C浮点数向零舍入 2019年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 输入一个单精度浮点数&#…

09-JVM垃圾收集底层算法实现

上一篇&#xff1a;08-JVM垃圾收集器详解 1.三色标记 在并发标记的过程中&#xff0c;因为标记期间应用线程还在继续跑&#xff0c;对象间的引用可能发生变化&#xff0c;多标和漏标的情况就有可能发生。 这里我们引入“三色标记”来给大家解释下&#xff0c;把Gcroots可达性…

uni-app动态tabBar,根据不同用户展示不同的tabBar

1.uni框架的api实现 因为我们用的是uni-app框架开发&#xff0c;所以在创建项目的时候直接创建uni-ui的项目即可&#xff0c;这个项目模板中自带了uni的一些好用的组件和api。 起初我想着这个效果不难实现&#xff0c;因为官方也有api可以直接使用&#xff0c;所以我最开始尝试…

DeeTune:基于 eBPF 的百度网络框架设计与应用

作者 | 百度APP云原生技术研发组 导读 随着云计算的技术的不断迭代演进&#xff0c;百度内部服务逐渐搬迁到云环境中&#xff0c;部署成本和效率取得明显收益&#xff0c;但一些可观测能力的短板和缺失逐渐显露&#xff0c;传统的方式往往通过植入代码进行修改来实现&#xff0…

esp-hosted 方案介绍

esp-hosted SDK esp-hosted 方案介绍 esp-hosted 方案主要为 Linux 或者 MCU 提供无线连接功能&#xff08;WiFi 或者 BT/BLE&#xff09; esp-hosted 解决方案包含了 esp-hosted FG 和 esp-hosted NG 两套方案 与传统 WiFi 网卡的区别在于 ESP 设备端需要烧录固件&#xff0…

RGMII 与 GMII 转换电路设计

文章目录 前言一、RGMII 接口的信号说明二、RGMII 发送的 FPGA 实现方案1. OPPOSITE_EDGE 模式2. SAME_EDGE 模式三、使用 FPGA 实现 RGMII 接口前言 RGMII 是 IEEE802.3z 标准中定义的千兆媒体独立接口(Gigabit Medium Independent Interface)GMII 的一个替代品。相较于 GM…

详解Redis之Lettuce实战

摘要 是 Redis 的一款高级 Java 客户端&#xff0c;已成为 SpringBoot 2.0 版本默认的 redis 客户端。Lettuce 后起之秀&#xff0c;不仅功能丰富&#xff0c;提供了很多新的功能特性&#xff0c;比如异步操作、响应式编程等&#xff0c;还解决了 Jedis 中线程不安全的问题。 …