[算法与数据结构]:递归

写在前面:本人算法小白,出生车辆工程,本科偏机械,硕士入了自动驾驶的坑,对于算法总是停留在一知半解的层次,最近在刷LeetCode,递归函数一直是自己的短板,对于其的理解如下,希望可以帮助到大家。欢迎留言,批评指正!!!

递归函数的定义

  • 百度:编程语言中,函数Func(Type a,……)直接或间接调用函数本身,则该函数称为递归函数。
  • 通俗理解:就是函数自己调用自己的实例

1+2+3+4+…+99+100,不使用递归的话,可以用循环
代码示例:

def sum():
	for i in range(1,101):
		sum1+=i
	return sum1

但是当使用递归函数时:

def sum_number(n):
	if n<=0:
		return 0
	return n+sum_number(n-1)
sum_number(100)

上述两行代码所实现的功能一致,刚刚接触的时候就想,能用循环为什么用这么抽象的东西,但是不然,递归的应用可以让整个函数的求解过程变得更加清晰。
L e i g h C a l d w e l l Leigh Caldwell LeighCaldwell S t a c k O v e r F l o w Stack OverFlow StackOverFlow中有过这么一段话:如果使用循环,程序的性能可能更高:如果使用递归,程序可能会更加清晰。

由于递归函数一直调用自己,所以在编写程序时,很容易出错,进而导致无限循环,程序出错。
编写递归函数时,必须告诉他何时停止递归,所以每个递归函数都有两部分构成:基线条件和递归条件。递归条件是递归函数何时调用自己,极限条件是函数不在调用自己,从而避免无限循环。
回头看代码:

def sum(n):
	if n < = 0:            # 基线条件 递归函数何时停止递归
		return 0
	else:                  # 递归条件 何时开始递归运算
		sum1=n+sum(n-1)       
	return sum1

简而言之,递归的核心思想:每一次递归,整体问题都要比原来减小,并且递归到一定层次时,要能直接给出结果!

递归函数编写时的步骤

每一个递归程序都遵循相同的基本步骤:

1.初始化算法。 递归程序通常需要一个开始时使用的种子值(seed value)。可以向函数传递参数,或者提供一个入口函数,这个函数是非递归的,但可以为递归计算设置种子值。

2.检查要处理的当前值是否已经与基线条件相匹配(base case)。如果匹配,则进行处理并返回值。是否已经满足基线条件。

3.使用更小的或更简单的子问题(或多个子问题)来重新定义答案。体现了分治的思想。

4.对子问题运行递归算法

5. 将结果合并入答案的表达式,返回结果

递归函数的溢出问题

递归函数为什么会溢出?
通俗理解: 递归函数在调用自己的时候,还没有退出,占内存,多了肯定会导致内存崩溃。

本质上来讲,在计算机中,函数调用是通过栈( s t a c k stack stack)这样数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会少一层栈帧。由于栈的大小不是无限的,所以,递归调用次数多了,会导致栈溢出。
在这里插入图片描述

图1 栈的示意图

尾递归优化

递归特性

  • 1.必须要有一个明确的结束条件, 否则就变成死循环导致栈溢出
  • 2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少,这句话的以上就是说,每进入一次递归,就会解决一些东西,数据量就会越来越小,最终解决了所有的问题,如果进入一次递归没有解决问题,那么不管递归多少层都没有意义,直到导致栈溢出。
  • 3.递归效率比较低,递归层次过多会导致栈溢出,意思是:每当进入一次函数调用,栈就会加一层栈帧,每当函数返回,就减少一层栈帧,由于栈不是无限大小的,所以,递归调用的次数过多,会导致栈溢出。

尾递归,进入下一个函数不再需要上一个函数的环境了,得出结果以后直接返回。
执行完一层调用下一层的时候,把这一层的数据给销毁掉,并且下一层和这一层没有关系,叫尾递归。

哈哈哈 很遗憾 Python 不支持尾递归优化!!

Notes:递归函数调用时,参数是一个个进去,满足基线条件后,参数也是一层层出来,递归调用栈!(LIFO)

def zero(n):
    n = n // 2
    print(n)
    if n == 0:
        return 'Done'
    zero(n)
    print(n)  # 1 2 5
'''
第一层会n=5,第二层会n=2,第三层会n=1,第四层n=0,符合条件程序停止。停止之后,程序的控制权会回到第三层调用第四层的位置,也就是zero(n),然后print出1,然后回到第二层print出2,最后回到第一层print出5。
整个程序是先一层层进去,然后在一层层出来。
'''
zero(10)  # 5 2 1 0 1 2 5
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值