一.恶魔小黑的故事
话说在这世界上有一个恶魔,他叫小黑,小黑正在跑100米长跑。小黑有一个特殊的超能力,就是能够在自己累的不能再动的时候,能够选择自己吃掉自己身体的一部分,进而获取古娜拉黑暗之神的赐予的洪荒之力,使他离100米的终点更近一步(当然,吃掉自己的一部分以后,他就变了他完整身体的一部分),同时他的意识会记录下来自己被吃的身体部分的顺序。而100米终点的奖励就是一块黑暗之石,能够让他瞬间按照被吃的顺序倒序(即先被吃掉的后长,后被吃掉的先长)长好身体上被吃而导致的残缺部分。可是他不能无限吃自己啊,那不就还没有到终点就把自己吃完而导致si翘翘了嘛。
二.递归函数详解
1.什么是递归
同样的,我们在解决一个问题时,调用了一个叫小黑的函数,小黑用了一次洪荒之力(函数执行了一次)还没有到终点(解决问题),这个时候他就可以再次调用自己(吃自己)从而获取动力,再次使用洪荒之力,当然吃自己是有限度的(出口,见下文)。有两种可能的结果,1是还没有吃到不能再吃自己,就到终点了,这个时候他拿到黑暗之石,恢复自己的残缺。2.是还没有到终点,便不能吃自己了,这个时候我们应该说:男嘉宾遗憾退场
好 这个时候我们来讲讲什么叫递归
递归就是就是在运行的过程中调用自己(奔向终点的过程中自己吃自己),构成递归需具备的条件:
- 子问题须与原始问题为同样的事,且更为简单;(他吃掉自己一部分以后还要是他,不能换另一个恶魔(函数)替他跑)
- 不能无限制地调用本身,须有个出口,化简为非递归状况处理。(不能无限的吃自己,会悄咪咪*翘翘的)
我们现在来讲讲递归函数
首先递归函数是一个函数,所以他有函数的基本形式,即
func 函数名A(参数列表) 返回值类型 {
函数体
return 返回值
}
不同的是在普通函数的函数体中加入调用自己的语句,这就是递归函数,所以
递归函数的基本形式:
返回值类型 函数名A(参数列表) {
if 终止条件 {
return 返回值
}else{
return 函数名A(参数列表)//调用函数的A自己
}
}
2.递归示例
1.递归计算求和
例如:1+2+3+4+5+6+7+8+9+10=?
func f(int n) int
{
if n==1{
return 1;//出口
}
else{
return (n+f(n-1))
}
//计算1+2+3+....+10
//第一次调用将f(10)转化为f(10)=10+f(9)
//第二次f(9)转为9+f(8),接上上面的就是f(10)=10+9+f(8)
//........
// 第九次调用将f(2)转化为f(2)=2+f(1)
//此时计算机知道f(1)=1
//最终将f(10)转化为f(10)=10+9+8+7+6+5+4+3+2+1
}
func main()
{
var num int
num=f(10)
//函数使用在定义之后,便不用再声明
//调用函数的A
}
注意事项:
1.递归一定要有条件限定,保证递归能停下来,否则会发生栈内存溢出;(函数被调用一次,就要在栈中记录下来,然后到回来的时候才知道按照上面顺序回来,这个调用关系被存放在栈中,调用的太多会导致栈被存满。也就是恶魔要知道自己身体是按照什么顺序被吃的,这样他才能倒序长回来啊,然后他不能一直吃,不然顺序太多,而他记不住了)
2.虽然设定限定条件,但递归次数依然不能太多,否则也会可能栈内存溢出;(和他不能一直吃,不然顺序太多而他记不住是一样的道理)
2.递归计算阶乘
下面我们来看求阶乘的例子:
计算5!=54321=?
func f(int n) int
{
if n == 1{
return 1
}else{
return n * f(n - 1)
}
}
func main()
{
n:=5
ret := f(5)
}
显然,我们可以分析得到:
1.第一次函数调用,将f(5)转化为f(5)=5f(4)
2.第二次函数调用,将f(4)转化为f(4)=4f(3)
3…
4.最后一步将f(2)转化为f(2)=2f(1)=21
5.所以计算机最终将f(5)转化为f(5)=54321
3.递归的改写
很明显的,计算求和我们可以使用for循环更加简便的书写。没错,确实是这样,一般而言能用递归做的问题使用for循环做看上去更简单。但是,像面对汉诺塔这类问题时,传统的循环方法比较难做,我们便使用递归函数。一般的,不建议使用递归函数
3.1计算求和改写为for循环
例如将计算1+2+3+4+5+6+7+8+9+10=?改写为for循环
func main(){
num :=0
for i :=1;i<=10;i++{
num=num+i
}
}
3.2计算递归改写为for循环
将计算5!=54321=?改写为for循环
func f(n int)int{
n:=5
num:=1
for i := 1; i <= n; i++{
num =num* i
}
}