递归

分治策略

当求解一个规模很大的问题的时候,可以考虑分解,即把原问题分解为若干个较小规模的问题处理,以便各个击破,分而治之,这就是分治的设计思想

如果求解的问题可以分解为k个子问题,且这些子问题都是可解的,并可利用这些子问题的解求出原问题的解,这种分治是可行的。

递归

递归是一个过程或者函数在其定义中直接或者间接调用自身的一种方法,就是利用系统堆栈,实现函数自身调用或者互相调用的过程。在通往边界的过程中,都会把单步地址保存下来,再按照先进后出进行运算。

递归算法通过函数或者过程调用自身将问题转化为本质相同但是规模较小的子问题,是分治策略的具体体现。

递归需要有递归关系式与边界条件,递归过程有递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

递归设计需要有递归关系,这是递归依据;同时需要有边界条件,这是递归基础,是控制递归过程结束的条件。

示例

1. 最开始接触递归算法的时候,我们一般是通过计算n的阶乘n!。

第一步:建立递归关系,注意到,当n>1的时候,n! = n*(n-1)!,这就是一种递归关系,对于特定的k!,它只与k和(k-1)!有关。

第二步:确定边界条件,递归边界为:n=1的时候,n!=1。对于任意给定的n,程序将最终求解到1!。

以下是上述问题的python代码实现:

def solution(n):
    if(n==1):   #递归边界
        temp = 1
    else:       #递归关系
        temp = n*solution(n-1)
    return temp
if __name__ == '__main__':
    n = int(input())
    print(solution(n))

2. 快速排序算法。这个算法是属于数据结构中八大排序算法之一,快速排序又称为分区交换排序,其基本思想是分治,即分而治之:在待排序的n个数据r[1,2,...,n]中任取一个数(例如r[1])作为基准,把其余n-1个数据分为两个区,小于基数的数放在左边,大于基数的数放在右边,这样分成的两个区实际上是待排序数据的两个子列。然后对这两个子列分别重复上述分区过程,直到所有子列只有一个元素,即所有元素排到位后,输出排序结果。

以下为快速排序算法的递归实现(python):

def quick(m1,m2,number):
    if(m1<m2):
        i=m1
        j=m2
        temp = number[i]  #选择一个基准
        while(i!=j):
            while(number[j]>=temp and j>i):
                j=j-1
            if(i<j):
                number[i] = number[j]
                i=i+1
            while(number[i]<=temp and j>i):
                i=i+1
            if(i<j):
                number[j] = number[i]
                j=j-1
        number[i] = temp
        quick(m1,i-1,number)
        quick(i+1,m2,number)
    return number
if __name__ == '__main__':
    number = list(input().split(" "))
    print(quick(0,len(number)-1,number))

3. 分区交换选择,在一个无序序列r[1],r[2],...,r[n]中,寻找第k小元素的问题称为选择。这里的第k小元素是指按照升序排列之后的第k个元素,特别地,当k=n/2时,即寻找位于n个元素中的中间位置,称为中值问题。

参照上面的分区交换的快速排序算法,在待选择的n个数据r[1,2,...,n]中任取一个数作为基准,把其余n-1个数据分为两个区,小于基准的数放在左边,大于基准的数放在右边,基准定位在s,则:

1) 若s=k,基准数即为所寻求的第k小元素

2) 若s>k,可知左边小于基准数的个数s-1>=k,则在左边的子区继续分区

3) 若s<k,可知所寻求的第k小元素在右边子区,则在右边的子区继续分区。

依此2)、3)继续,知道出现1)结束,输出结果。

以下为上述问题的python代码实现:

def quick(m1,m2,k,number):
    if(m1<m2):
        i=m1
        j=m2
        temp = number[i]  #选择一个基准
        while(i!=j):
            while(number[j]>=temp and j>i):
                j=j-1
            if(i<j):
                number[i] = number[j]
                i=i+1
            while(number[i]<=temp and j>i):
                i=i+1
            if(i<j):
                number[j] = number[i]
                j=j-1
        number[i] = temp
        if(i==k-1):
            return number[i]
        elif(i>k-1):
            return quick(m1,i-1,k,number)
        else:
            return quick(i+1,m2,k,number)
if __name__ == '__main__':
    number = list(input().split(" "))
    k = int(input())
    print(quick(0,len(number)-1,k,number))

总结:递归数据要不断的进栈出栈,且存在大量的重复计算。递推免除了数据进出栈的过程,直接从边界出发,逐步推出函数值,避免了重复计算。因而递推效率远远高于递归。在数据结构中树中利用了很多递归的思想,包括树的定义、树的先中后序遍历都利用了递归的思想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值