用类比方式学习编程中函数递归(个人理解仅供参考)(内含汉诺塔问题的求解)

目录

1.前言

2.递归的数学模型

3.相关的c语法

4.将递归的数学模型写成编程语言

5.利用类比方法将实际问题的代码写成函数递归的形式

例1:

 例2:

6.汉诺塔问题的求解


1.前言

本人在学习函数递归编程方法的过程中,发现用类比的方式学习递归法可帮助我们在各种编程问题中将函数递归法运用于代码设计中。

在我看来,函数递归最底层的思维模型是:数学中的数列的递推公式(数列的递推公式是研究数列性质和求通项公式的核心,将递推迭代思维模型应用于代码设计中,就产生了函数递归).

2.递归的数学模型

现在我们任意给出的一个数列 {An} 的首项和它的递推公式:

A1 == 1, An ==  2*A(n-1) +  1 (n>1)

在数学中求解该数列的通项公式的方法有很多种,其中有一种叫做迭代法:(迭代法可以用于求解各种递推公式为一阶递推式的数列的通项) 

所谓迭代法就是将递推公式中的项按照递推公式本身逐项展开(即从An开始一直逐项递值展开到A1,然后通过计算返回出结果

接下来我们用迭代法来试求{An}的通项公式: (n>1)

An=2*A(n-1) + 1 = 2*(2*A(n-2) +1) +1 = 2*(2*(2*A(n-3)+1)+1) +1=................................

以这种方式一直展开到A1再通过归纳整理便可以得出An的通项公式.

3.相关的c语法

我们知道,计算机最擅长做的事情就是重复大量地进行同一形式的计算。然而在迭代法中,我们从An开始按照 同一个递推公式 将其逐项展开直到A1这种算法显然十分符合计算机的思维模式.在C语言中我们允许函数嵌套自身即:       

int  func(int n)    
{func(n); return 0;
}

     

调用函数的时候 函数本身在返回输出之前会先调用自身并且这样的过程会不断重复进行

为了能够最终让函数返回输出,我们要对函数向内递值进行条件约束 并且每次向内传递的值都要逼近约束条件比如:

   


int func(int n) 
{if(n>=1){ func(n-1);}else{return0;}
}

 这样的话函数就会逐层向内递值n次后再逐层返回输出. 

4.将递归的数学模型写成编程语言

现在我们想让计算机帮我们求数列{An}的任意一项的值.要求设计一个函数int func(int)输入正整数n作为形参,函数便返回An的值.

思路引导:{An}的递推公式 An= 2*A(n-1)  + 1    

如果递推公式中An相当于代码中的 func(n),那么A(n-1)则相当于代码中的func(n-1)

结合迭代法求通项的思路和相关C语法便可写出如下代码

int func(n)
{if(n>1)                  //递推公式的成立条件{return 2*func(n-1)+1; //数列的递推公式} else{return 1 ;            // 数列首项为以1}
}

计算机在执行这段代码时就会自动帮助我们完成迭代的过程.(该过程中函数减值向内递值直到最后一次向内递入整数1【“递”过程】,再从最内层函数开始逐层向外返回数值【“归”过程】并最终得到结果)(递推公式决定函数递值的方式和函数结构,首项决定归值节点

进一步思考可以得知,任意给定一个数列,只要我们知道其首项和递推公式,我们就可以写出与上面代码形式相同的代码用于求任意项的数值.

5.利用类比方法将实际问题的代码写成函数递归的形式

例1:

问题:设计一个函数代替库函数strlen()  ,用于求字符串长度,形参是char*类型 返回值是int类型.

我们自定义函数取名叫做restrlen() 

假设我们要求字符串“bite”的长度. 创建字符串数组char arr[]="bite".

先抽象出一个数列的某一项 restrlen("bite")

我们可以得到递推关系 restrlen("bite") = restrlen("ite") + 1

鉴于题目要求,求“bite”长度时我们只能将arr即字母b的地址传入函数中

那么restrlen("bite")就相当于restrlen(arr),类似地,restrlen("ite")就相当于restrlen(arr+1)

于是递推关系就变成了 restrlen(arr)=restrlen(arr+1) +1  

该问题中首项是restrlen(arr+x) = 0 , x为某一整数 并且满足*(arr+x)="\0"  于是我们便有了如下代码:

int restrlen(char* x)
{if(*(x+1)!=0)                  //类似于递推公式成立条件{return restrlen(x+1) +1;  //类似于数列递推公式}else{return 0;                 //类似于首项}
}

 例2:

问题:设计一个函数当输入一个整数时,函数会依次输出打印出该整数每一个十进制位上的数字如:输入123 打印1 2 3

我们给函数取名叫做 prt 以输入123为例子

要先打印出1 那么1肯定在最内层函数完成输出(归值从内而外)

先抽象出一个数列的项prt(123) 其前一项可以抽象为prt(12)

那么我们便可以抽象出其递推公式  prt(123)= prt(12) + "printf("%d",123 %10)

如果数列的中n相当于“123”,那么n-1则相当于“123/10”

当输入值整除10等于0时就得到“首项” (类比意义上) “首项”的值为0

由于函数输出方式为打印输出所以无需返回值(注意要先向内层递值再打印输出)

void Print(int n)
{if(n/10!=0){Print(n/10);printf("%d",n%10);}
}

6.汉诺塔问题的求解

先从数学角度对汉诺塔问题进行分析:现在设 将A柱上n个圆盘借助B柱移动到C柱 需要移动圆盘的总次数为Xn.
显然我们可以得到数列{Xn} ,其中n>=1     接下来我们来研究该数列的递推公式 即尝试研究Xn与Xn-1的关系
从特殊到一般的方法对问题进行分析 我们可以分析出如下规律;

  1. 为了将A柱上n个圆盘借助B柱移动到C柱,我们必须经历这样一个步骤:将A柱上最大的圆盘移动要C柱上.
  2. 在完成1.分析中所述的步骤之前,A柱上必须只剩一个最大的圆盘,C柱必须的空的,此时B柱上则有n-1个圆盘
  3. 因此我们必须在游戏开始后先完成另外一个步骤:将A柱上n-1个圆盘借助C柱移动到B柱上.
  4. 我们称分析3.中所述步骤为:第一步骤(我们无需理会该步骤具体是如何进行的)称分析1.中所述步骤为:第二步骤
  5. 很显然若Xn代表n个圆盘的汉诺塔问题中需要移动圆盘的总次数,那么第一步骤需要移动圆盘的总次数为Xn-1次
  6. 同时,第二步骤需要移动圆盘的总次数为1次
  7. 在完成了第一步骤和第二步骤后我们便可以无视C柱上那个最大的圆盘接着分析下一步
  8. 接下来,我们只需 将B上的n-1个圆盘借助A柱移动到C柱 我们称这一步为 第三步骤(我们同样无需理会该步骤具体是如何进行的)
  9. 显然完成第三步骤所需移动圆盘的总次数同样为Xn-1 次

通过上述分析我们可以得到结论:为了解决n(n>1)个圆盘的汉诺塔问题我们需要经历如下三个步骤(设总移动圆盘的次数为Xn) (这里A为起始柱,B为过渡柱,C为目标柱)
第一步骤:将A柱上n - 1个圆盘借助C柱移动到B柱上(移动Xn-1次)(这里A为起始柱,C为过渡柱,B为目标柱)
第二步骤:将A柱上剩下的那个最大的圆盘移动要C柱上(移动1次)   
第三步骤:将B上的n - 1个圆盘借助A柱移动到C柱(移动Xn-1次)(这里B为起始柱,A为过渡柱,C为目标柱)
即得到数列的递推公式(n>1):      

          Xn       =     ( Xn-1 )   +   (1)   +   (Xn-1)/*移动圆盘的总次数*/    /*第一步骤*/ /*第二步骤*/   /*第三步骤*/

当n==1时显然我们只需执行一次第二步骤 即X1==1

利用上面的数学结论我们来尝试解决汉诺塔的c语言编程问题
编程的要求是:设计一个函数 输入形参n作为初始圆盘总数 函数(比如输入n==3时)以如下的形式打印输出(以这种形式告诉用户解决n个圆盘的汉诺塔问题的每个具体的圆盘移动步骤)

               A-->C        A-->BC-->BA-->CB-->AB-->CA-->B

根据数学递推公式的分析我们可以初步得出:汉诺塔函数中我们有两个减值向内层函数递值的步骤(“递”步骤) 中间还有一个移动单个圆盘的步骤
很显然中间那个移动单个圆盘的步骤可以作为我们函数递归的返回输出节点(即从最内层函数开始向外层函数返回输出的“归”步骤)
于是我们可以得到如下函数递归框架:

    void Hanoi(int n)     //总过程:将A柱上n个圆盘借助B柱移动到C柱{Hanoi(n - 1);     /*第一步骤(函数向内递值 即“递”的步骤)*/printf() ;        /*第二步骤(该步骤具体实行打印输出 即"归"的步骤)*/Hanoi(n - 1);     /*第三步骤(函数再一次向内递值)*/}

以上便是根据汉诺塔问题数学分析得出的基本递归框架
然而为了将 《最外层函数的“将A柱上n个圆盘借助B柱移动到C柱”过程》以及《第一个内层函数的“将A柱上n - 1个圆盘借助C柱移动到B柱上”过程》以及《第二个内层函数的“将B上的n - 1个圆盘借助A柱移动到C柱”过程》  三者区分开来
我们必须引入三个字符形参代表A B C三个柱子 并且通过这三个字符形参在函数小括号()中的排列顺序的区别来区分前句分析的三个过程
于是我们可以进一步填充函数递归框架 并给出函数向内递值的限制条件完成代码设计

int count = 0;
void Hanoii(char a, char b, char c, int n)          
{if (n >= 1){  Hanoii(a, c, b, n - 1);                     count++;printf("%d.  %c-->%c\n", count, a, c);      Hanoii(b, a, c, n - 1);                      }
}
int main()
{char x = 'A';char y = 'B';char z = 'C';int k = 0;scanf("%d", &k);Hanoii(x, y, z, k);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我想,有间花房

你带我走进你的花房,我无法逃脱花的清香,我不知不觉忘记了方向,你说我世上最坚强,我说你世上最善良,你不知不觉和花儿一样 也许每一位 爱花的姑娘,都想有一间属于自己 的花 房 ,在悠闲的午后&am…

花房集团CEO于丹内部信:上市即暴富年代已一去不复返

雷递网 乐天 12月12日 花椒母公司花房集团(股票代码为:“03611”)今日在港交所上市,发行价为2.8港元,募资净额为7240万港元。 花房集团开盘价为3.29港元,较发行价上涨17.5%;截至目前&#xff0c…

花房集团上市:市值超30亿港元 周鸿祎连收两个香港IPO

雷递网 雷建平 12月12日 花椒母公司花房集团(股票代码为:“03611”)今日在港交所上市,发行价为2.8港元,募资净额为7240万港元。 花房集团开盘价为3.29港元,较发行价上涨17.5%;截至目前&#xff…

花房集团上市,走向元宇宙新征程

12月12日,花房集团在港交所成功上市,首日便受到追捧,当日最高涨幅达28.75%。 继360、360数科、鲁大师后,这是“红衣教主”周鸿祎收获的第四个IPO。 花房集团作为直播界元老之一,两年内三次申请IPO,终于在…

花房集团:直播老将终赴IPO

寒冬之下,花房集团如何破局? 12月12日,直播界“元老”花房集团(下称“花房”,03611.HK)正式挂牌港交所。 花房此次IPO发行价为2.8港元/股,募资净额为7240万港元,开盘价为3.29港元/…

如果金融男和IT男同时追你,你选谁?

对于金融女心仪对象排行榜的前两名, 金融男和IT男的地位是不可动摇了, 要说两个行业的不同之处 , 最大的区别在于一个是经济领域, 一个是产业领域 而另一个区别呢? 当然是从事这两种行业的人群不同啦, 具…

会泡妞的程序员都是怎么撩妹子的?

来自:这个好玩吗 链接:https://www.cnblogs.com/lzjtdxfxl/p/5493039.html 传说,每一个程序员上辈子都是折翼的天使 身体好、智商高、逻辑思维能力强 挣得多、花得少、死得还比对方早 王者级的程序员是有情怀的 在他(她&#xff0…

软考必备资料大放送,全科目软考资料都给你备好了!

软考作为IT领域的国家级证书 可以积分落户、评职称、抵个税…含金量高 现在有越来越多的人加入了软考的备考大军 新一轮的软考考试马上要开始了 你准备好了吗? 下面是给大家整理好的软考备考资料包 上面展示的资料只是冰山一角,软考科目众多&#…

【广工考试笔记】计算机网络考试速成笔记

范围 网络协议,服务 网络四层协议的功能与包含的协议 数据链路层 差错检测 ,物理地址,以太网,局域网的扩展, 物理层 数据传输速度,频率,波长,速度,编码 网络层&…

《软考填涂答题卡须知》

考试临近,今天主要是给大家说下答题卡的填涂注意事项,希望考生们看完后可以避免一些小失误。除信息处理技术员和多媒体应用制作技术员采取笔试与上机操作考试相结合的形式外,其他各种考试都采用笔试形式。考试实行全国统一大纲、统一试题、统…

考试管理系统

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字): 模块划分:老师模块、班级模块、学生模块、课程模块、试题模块、试卷模块、 组卷模块、考试模块、答题模块 管…

【CSP考前复习】关于考试时的注意事项

前言 作为一名已经服役4年的老年OI选手,经历过的考试已经是数以百计了。在这么多次考试中,爆零垫底是常有的事,运气好了靠暴力得到好名次的事也经常发生。那么,CSP临近,我想有必要好好整理一下这些问题和经验。 一、…

CKA OFFCIAL TEST准备工作考试说明练习题

文章目录 1. 准备工作1.1 证书详情1.2 考试注意事项 2. 考试说明2.1 考试环境2.2 考试期间允许的资源2.3 考试技术说明2.4 可接受的测试地点2.5 其他资源2.A 考试小提示 3. 练习题Task 1. RBAC - role based access control(4/25%)Task 2. drain - highl…

CCNA考试流程、考试费用及考场介绍

4月15日CCNAHCIA新一轮班级开班 CCNA(Cisco Certified Network Associate)思科认证网络工程师 一、CCNA认证考试流程 ccna考试认证,先学习CCNA理论知识,然后下载CCNA考试题库,预约考试,参加并通过考试。 C…

股票ctp交易接口是什么?

股票ctp交易接口是什么?CTP接口除官方发布的C动态库外,很多人也提供了Python、Java、C#等各主流语言的接口,可搜索相应的开发方法。一个连接能够查询的股票数量是有限的,性能也不高,但是可以创建多个api实例并发工作&a…

美股投资指南 – 网上美股开户其实很简单

美股开户教程 – 从香港招行到Firstrade 犹豫再三,觉得还是把这帖子贴在这里吧,文章是我写在自己新开的博客里的,分上下两篇,记录自己在美股开户中碰到的问题,写的不咋怎么样都是粗记录,既然成文就公布吧&a…

阿里云Redis之:为阿里云Redis申请公网地址(十九)

1.申请公网地址 1)点击实例信息—>找到连接信息—>找到公网访问—>申请连接地址 2)填写外网连接地址,然后填写端口号,最后点击确定。 3)外网地址申请成功 2.通过Redis客户端连接云Redis 阿里云官方反馈公网地址不能通过Redis Desktop Manager连接,存在兼容性问…

阿里云申请域名及域名配置https

1、阿里云域名申请 买到域名之后,要对域名进行实名认证(上传身份证并拍照)(阿里云审核一天) 2、域名工信部备案 1、阿里云域名备案,这个也要实名认证,其中阿里云员工审核并打电话(…

天池_阿里音乐流行趋势预测大赛(1) —— 赛题分析

本文以天池大数据竞赛的阿里音乐流行趋势预测大赛为背景,将机器学习实战的背景、模型、算法、代码和结果等都整理下来,放在博客中,算是对自己知识的整理吧,有兴趣的朋友也可以看看一起讨论学习。 由于很多比赛和项目是由第三方提…

申请阿里云免费证书

阿里云免费SSL证书申请 阿里云免费SSL证书是赛门铁克(Symantec)品牌的,免费证书只能保护一个域名(带www和不带www可以通用)。 阿里云个人账号和企业账号均可申请,多个域名可以申请多个免费证书,…