【c语⾔】递归算法解析
⼀、基本概念:putchar函数
c语⾔通过运⾏时堆栈来⽀持递归的实现的。递归函数就是直接或者间接调⽤⾃⾝的函数。
这⾥有⼀个简单的程序,可⽤来说明递归。程序的⽬的是将⼀个整数从⼆进制形式转化为可打印的字符形式,例如给出⼀个值4267,我们需要⼀次产⽣‘4’,‘2’,‘6和‘7’。如果在printf函数中使⽤了%d格式码,它就会执⾏这类处理。
这⾥的算法思路是,把这个值反复除以10,并打印各个余数。例如,4267除10的余数是7,但是我们不能直接打印这个余数。我们需要打印的是机器字符集中表⽰数字‘7’的值。在ASCII码中,字符‘7’的值是55,所以我们需要在余数上加上48来获取正确的字符。但是,使⽤字符常量⽽不是整型常量可以提⾼程序的可移植性,谷歌母公司酝酿裁减员工上万人
‘0’+0=‘0’
linux可视化界面‘0’+1=‘1’
‘0’+2=‘2’
从这些关系中,我们很容易看出在余数上加上‘0’就可以产⽣对应字符的代码。接着就打印出余数。下⼀步是取得商,4267/10=426.然后⽤这个值重复上述这个步骤。
这种处理⽅法存在的唯⼀问题是它产⽣的数字次序正好相反,它们是逆序打印的,可以使⽤递归来修正这个问题。
#include<stdio.h>
void binary_to_ascii(unsigned int value)
{
深情来的太迟哪里可以看unsigned int quotient;
quotient = value / 10;
if(quotient != 0)
binary_to_ascii(quotient);
putchar(value%10+'0');
}
update语句的解析这个函数就是递归性质的,因为它包含了⼀个对⾃⾝的调⽤。乍⼀看,函数似乎永远不会终⽌。但函数调⽤时,它将调⽤⾃⾝,⼀直调⽤⾃⾝,似乎会永远调⽤下去实际上并不会出现这种情况。
这个程序的递归实现了某种类型的螺旋状while循环。while循环在循环体每次执⾏时必须取得某种进展,逐步迫近终⽌条件。递归函数也是如此,它在每次递归调⽤后都必须越来越迫近某种限制条件。当递归函数符合这个条件时,它便不再调⽤⾃⾝。
在上述程序中,递归函数的限制条件是quotient为零,在每次递归调⽤之前,我们都把quotient除以10,所以每递归⼀次,它的值就越来越接近零。当它最终变成0时,递归便终⽌。
这段代码的⼯作流程是什么样⼦呢?
1、将参数值除以10
2、如果quotient的值为⾮零,调⽤binary_to_ascii打印quotient当前值的各位数字,
3、接着打印步骤1中除法运算的余数
注意:在第⼆个步骤中我们打印的是quotient当前值的各位数字。我们所⾯临的问题和最初的问题完全相同,只是变量quotient的值变⼩了。我们⽤刚刚编好的函数来解决这个问题,由于qutient的值越来越⼩,所以递归最终会终⽌。
为了理解递归的⼯作原理,我们需要追踪递归的执⾏过程,⽽追踪的关键就是变量是如何存储的。当函数被调⽤时,它的变量的空间是创建于运⾏时堆栈上的。以前调⽤的函数的变量仍保留在堆栈上,但它们被新函数的变量所掩盖,因此是不能被访问的。调⽤⾃⾝时也是相同的,每⼀次调⽤产⽣的新变量掩盖前⼀次创建的变量。
上⾯程序中⼀共有两个变量,⼀个是参数value⼀个是局部变量quotient过程如图所⽰,当前可以访问的变量位于栈顶,其它调⽤的变量⽤灰⾊阴影,表⽰它们不能被当前函数访问。
假定我们就以4267这个数字作为参数,刚开始执⾏时,堆栈的内容如下:
es6 class执⾏除运算后,堆栈变为:
经过if语句判断quotient的值不为0,开始递归调⽤,第⼆次调⽤开始,堆栈如图所⽰:
堆栈上创建了⼀批新的变量,隐藏了前⾯的那批变量,除⾮当前递归调⽤直接返回否则阴影部分变量就不能被访问,再次执⾏除法之后,堆栈内容如下:
if语句进⾏判断发现quotient的值是42仍然不是0,继续递归调⽤,并创建变量,执⾏完除法之后,堆栈内容如下:
if语句继续判断,发现quotient值为4,仍然不为0,继续执⾏递归调⽤,执⾏除法运算之后,堆栈内容如下:
现在quotient的值为0,if条件判断之后不再递归调⽤,开始打印输出,然后函数返回并开始销毁堆栈上的变量值。
每次调⽤putchar得到变量value的最后⼀个数字,⽅法是对value进⾏模10取余运算,其结果是⼀个0-9之间的整数,把它与‘0’相加,其结果便是对应这个数字的ASCII字符,然后把这个字符打印出来。
然后函数返回,变量从堆栈中销毁,接着递归调⽤的前⼀次继续执⾏,它所⽤的是⾃⼰的变量,它们位于堆栈的顶部,它的value值是42,所以使⽤putchar后打印出来的数字是2
接着递归函数继续返回,此时位于堆栈顶部的是递归函数前⼀次调⽤的变量,递归调⽤从这个位置开始继续执⾏,这次打印的数字是6,在这次调⽤返回之前,堆栈的内容如下:
回到最初的调⽤,这次调⽤打印出数字7,也就是它的value值除10的余数
堆栈内容如下:
到这⾥这个递归函数彻底返回到其他函数调⽤它的地点,这时候把打印出来的字符⼀个接⼀个拼在⼀起就能看到正确的结果: 4267
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论