递归算法基本概念详解(go语言基础语法)

本文通过恶魔小黑的故事引入递归的概念,详细解释了递归函数的工作原理,并提供了递归计算求和与阶乘的示例。同时,讨论了递归的局限性,如栈内存溢出问题,并展示了如何将递归改写为for循环。递归在解决某些问题时虽简洁,但需谨慎使用。
摘要由CSDN通过智能技术生成

一.恶魔小黑的故事

话说在这世界上有一个恶魔,他叫小黑,小黑正在跑100米长跑。小黑有一个特殊的超能力,就是能够在自己累的不能再动的时候,能够选择自己吃掉自己身体的一部分,进而获取古娜拉黑暗之神的赐予的洪荒之力,使他离100米的终点更近一步(当然,吃掉自己的一部分以后,他就变了他完整身体的一部分),同时他的意识会记录下来自己被吃的身体部分的顺序。而100米终点的奖励就是一块黑暗之石,能够让他瞬间按照被吃的顺序倒序(即先被吃掉的后长,后被吃掉的先长)长好身体上被吃而导致的残缺部分。可是他不能无限吃自己啊,那不就还没有到终点就把自己吃完而导致si翘翘了嘛。

二.递归函数详解

1.什么是递归

同样的,我们在解决一个问题时,调用了一个叫小黑的函数,小黑用了一次洪荒之力(函数执行了一次)还没有到终点(解决问题),这个时候他就可以再次调用自己(吃自己)从而获取动力,再次使用洪荒之力,当然吃自己是有限度的(出口,见下文)。有两种可能的结果,1是还没有吃到不能再吃自己,就到终点了,这个时候他拿到黑暗之石,恢复自己的残缺。2.是还没有到终点,便不能吃自己了,这个时候我们应该说:男嘉宾遗憾退场

好 这个时候我们来讲讲什么叫递归
递归就是就是在运行的过程中调用自己(奔向终点的过程中自己吃自己),构成递归需具备的条件:

  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)=4
f(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
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是一只土拨鼠呐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值