zoukankan      html  css  js  c++  java
  • 递归函数与算法

    一、递归函数

    1.1、定义

      在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

    1.2、递归函数特性

    1. 必须有一个明确的结束条件;
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。
    4. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

     2.1、递归的最大深度——997

      递归函数如果不受到外力的阻止会一直执行下去。但是我们之前已经说过关于函数调用的问题,每一次函数调用都会产生一个属于它自己的名称空间,如果一直调用下去,就会造成名称空间占用太多内存的问题,于是python为了杜绝此类现象,强制的将递归层数控制在了997

    示例如下:

     1 # 997理论
     2 def foo(n):
     3     print(n)
     4     n += 1
     5     foo(n)
     6 foo(1)
     7 # 结果
     8 ...
     9 995
    10 996
    11 997
    12 报错信息:RecursionError: maximum recursion depth exceeded while calling a Python object
    View Code

    由此我们可以看出,未报错之前能看到的最大数字就是997.当然了,997是python为了我们程序的内存优化所设定的一个默认值,我们当然还可以通过一些手段去修改它:

    import sys
    print(sys.setrecursionlimit(100000))

    我们可以通过这种方式来修改递归的最大深度,刚刚我们将python允许的递归深度设置为了10w,至于实际可以达到的深度就取决于计算机的性能了。不过我们还是不推荐修改这个默认的递归深度。

    2.2、递归的应用示例

    示例1:

    已知alex比egon大两岁,egon比wusir大两岁,wusir比无alan大两岁,alan为40岁,求alex的年龄

     1  金鑫    40
     2 武sir    42
     3 egon    44
     4 alex     46

    根据几个人的关系,分析结果如下:

    age(4) = age(3) + 2     #alex的年龄
    age(3) = age(2) + 2     #egon
    age(2) = age(1) + 2     #wusir
    age(1) = 40             #alan

     因此,计算Alex年龄的递归函数如下:

    def age(n):
        if n == 1: return 40
        else: return age(n-1)+2
    print(age(4)) #46

     示例2:

    递归函数与三级菜单

    #三级菜单
    menu = {
        '北京': {
            '海淀': {
                '五道口': {
                    'soho': {},
                    '网易': {},
                    'google': {}
                },
                '中关村': {
                    '爱奇艺': {},
                    '汽车之家': {},
                    'youku': {},
                },
                '上地': {
                    '百度': {},
                },
            },
            '昌平': {
                '沙河': {
                    '老男孩': {},
                    '北航': {},
                },
                '天通苑': {},
                '回龙观': {},
            },
            '朝阳': {},
            '东城': {},
        },
        '上海': {
            '闵行': {
                "人民广场": {
                    '炸鸡店': {}
                }
            },
            '闸北': {
                '火车战': {
                    '携程': {}
                }
            },
            '浦东': {},
        },
        '山东': {},
    }
    三级菜单menu
    #递归函数实现三级菜单
    def threeLM(dic):
        while True:
            for k in dic:print(k)
            key = input('input>>').strip()
            #按b键返回上一级,按q键则退出函数
            if key == 'b' or key == 'q':return key
            elif key in dic.keys() and dic[key]:
                ret = threeLM(dic[key])
                if ret == 'q': return 'q'
    
    threeLM(menu)
    #结果如下
    北京
    上海
    山东
    input>>北京
    海淀
    昌平
    朝阳
    东城
    input>>海淀
    五道口
    中关村
    上地
    input>>五道口
    soho
    网易
    google
    input>>soho
    soho
    网易
    google
    input>>
    递归函数实现
    #堆栈实现三级菜单
    def StackThreeLM(dic):
        l = [menu]
        while l:
            for key in l[-1]:print(key)
            k = input('input>>').strip()   # 北京
            if k in l[-1].keys() and l[-1][k]:l.append(l[-1][k])
            elif k == 'b':l.pop()   #返回上一级
            elif k == 'q':break     #退出操作
    
    StackThreeLM(menu)
    利用堆栈实现

    二、二分查找算法

    l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
    比如从这个有序列表中,要查找66的索引,二分查找66索引位置的实现过程如下:

    二分查找算法代码如下:

    #二分查找算法
    def find(l,aim,start=0,end=None):
        if end == None:end = len(l)-1
        if start <= end:
            mid = (end - start) // 2  + start
            if l[mid] > aim:
                return find(l,aim,start=start,end=mid-1)
            elif l[mid] < aim:
                return find(l,aim,start=mid+1,end=end)
            elif l[mid] == aim:
                return mid
        else:
            return None
    l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
    print('ret :',find(l,66))    #ret : 17
    View Code
     
  • 相关阅读:
    [BTS] The adapter "SQL" raised an error message. Details "新事务不能登记到指定的事务处理器中。 ".
    [BTS] 新事务不能登记到指定的事务处理器中
    [BTS] RFCTYPE RFCTYPE_DATE with length 8 and decimals 0
    [BTS]Could not find stored procedure.
    [BTS] SAP Adapter Retrieving the COM class factory for component
    [BTS]Unable to display adapter user interface.
    [BTS]BizTalk Performance Counters
    [BTS] Error in Check Transaction: 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))
    [BTS] 可能会经常用来参考的一段XSLT
    [BTS] Unable to communicate with MessageBox BizTalkMsgBoxDb on SQL Instance
  • 原文地址:https://www.cnblogs.com/lioushell/p/8480596.html
Copyright © 2011-2022 走看看