数据结构与算法(一)递归

释义

      递归就是函数自己调用自己,举个例子就是俄罗斯套娃。

用途

      递归提供了执行迭代任务的优雅并且强大的解决方案。

要点

      递归分为两部分,一部分是递归条件的定义,另一部分是终止条件的定义,在俄罗斯套娃中,递归条件就是空心的套娃内部含有套娃,而终止条件就是实心的套娃。

分类

    递归分为线性递归(每个递归调用一次自己),两路递归(每个递归中调用两次自己),多重递归(调用多次自己)。

示例

(1) 阶乘

          n ! =   n * ( n - 1 ) !          if  n>=1            (递归条件)

               =  1                              if  n = 0           (终止条件)

算法如下:

def factorial(n):
    if n == 0:
        return 1
    else:
        return n*factorial(n-1)

 (2) 二分法查找:在含有n个元素的有序序列中有效定位目标值。

         在有序序列中查找元素,最简单的办法就是通过for循环一个一个检查,时间复杂度为O(n),如果改为二分法查找,时间复杂度为Log(n),性能可以获得巨大提升。

        二分法查找算法:bin_search( data , target , low , high )

        首先有三个参数,low,hign,以及mid 。low和high分别为有序序列的起始位置和终止位置的索引,mid=[(low+high)/2]向上取整。mid为序列中间位置的数据索引。

       递归情形如下:

     (1)计算mid 如果目标值等于data[mid],终止递归。

     (2)如果targrt<data[mid],则说明target在low和mid之间,执行bin_search( data , target , low , mid-1 )

     (3)如果target>data[mid],z则说明target在mid和high之间,执行bin_search( data , target , mid+1,high)

    算法如下:

def bin_search(data,target,low,high):
    '''
       return True if target is in data.
    '''
    if low>high:
        return False
    else:
        mid = (low+high)//2
        if target == data[mid]:
            return True
        elif target <data[mid]:
            return bin_search(data,target,low,mid-1)
        else:
            return bin_search(data,target,mid+1,high)

注:递归分为线性递归(每一步调用一次自己)。二路递归(每一步调用两次自己),多路递归。递归的使用有技巧,参看下方的斐波那契数列的两种实现办法:

(3)斐波那契数列的递归实现

    1)斐波那契数列最简单的理解:通过两路递归来实现

           F0=0                       (n=0)

           F1=1                       (n=1)

           Fn=Fn-1+Fn-2        (n>1)

      算法如下:

def fibonacci(n):
    if n>1:
        return fibonacci(n-2)+fibonacci(n-1)
    else:
        return n 

       这种办法可以实现斐波那契数列,但是效率比较低,因为每次递归都需要进行两个递归,导致第n个数列的计算速度是n-2的二倍还要多,所以整体呈指数增长,效率非常低。

  2)我们可以对算法进行改造,使其每次只需要递归一次,比如:定义一个递归函数,该函数每次返回连续的斐波那契数列:(Fn,Fn-1),因为如果把斐波那契数列两个两个一组拆开,你会发现Fn=(a,b),则 Fn+1=(b,a+b),用函数表示,如下:

def fibonacci(n):
    if n<=1;
        return (n,0)
    else:
        (a,b)= fibonacci(n-1)
        return (a+b,a)

        对比:

       利用斐波那契数列相邻两个元素之间的关系,经过改造,可以看出,原先需要两路递归,改造后仅需要一次递归,所以改造后时间复杂度将为O(n)。

(4)线性递归逆置序列元素

        算法如下:

def reverse(S,start,stop):
    if start == stop-1:
        S[start],S[stop-1] = S[stop-1],S[start]
        reverse(S,start+1,stop-1)

        这个没啥好说的,但要注意隐含条件,当起始元素的索引等于最后一个元素的索引时,隐含条件是数列为空,当起始元素的索引等于最后一个元素的索引减去一时,数列已经递归到剩下一个元素,这两种情况下都不需要逆转。当len(S)为偶数时,会递归到第一种情况,当len(S)为奇数时,会递归到第二种情况。

 

 

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值