python专题 --- 递归

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

举例如阶乘函数,其数学递归定义如下:

对应的算法实现

def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)

实际的执行过程为:

===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120

对应的思路图为:

 

递归函数特性:

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

递归的概念很简单,下面对遇到的几个递归实例进行总结,以方便后续回顾:

1. 二分查找

2. 快速排序

3. 遍历多重列表元素

4. 汉诺塔

# 方法一:
def quicksort1(nums):
    if len(nums) <= 1:
        return nums

    # 左子数组
    less = []
    # 右子数组
    greater = []
    # 基准数
    base = nums.pop()

    # 对原数组进行划分
    for x in nums:
        if x < base:
            less.append(x)
        else:
            greater.append(x)

    # 递归调用
    return quicksort1(less) + [base] + quicksort1(greater)

# 方法二
def quick_sort3():
    def fast_sort(li):
        if len(li) > 1:
            l, mid ,r = deal(li)
            return fast_sort(l) + [mid] + fast_sort(r)
        else:
            return li

    def deal(li):
        left = 0
        right = len(li) - 1
        temp = li[-1]
        tab = True

        while left < right:
            if tab:
                if li[left] <= temp:
                    left += 1
                else:
                    li[right] = li[left]
                    tab = not tab
                    right -= 1
            else:
                if li[right] >= temp:
                    right -= 1
                else:
                    li[left] = li[right]
                    tab = not tab
                    left += 1
        else:
            li[left] = temp
        return li[:left], temp, li[right+1:]

# 方法三:
def quick_sort2():
    def quick(li,left,right):
        if left<right:
            mid=partition(li,left,right)
            quick(li,left,mid-1)
            quick(li,mid+1,right)
        return li

    def partition(li,left,right):
        pivot=li[left]
        while left<right:
            while left<right and pivot<li[right]:
                right-=1
            li[left]=li[right]

            while left<right and pivot>li[left]:
                left+=1
            li[right]=li[left]
        li[left]=pivot
        return left

折半查找

# 折半查找
l = list(range(0, 100, 2))
s = 85

# 方法一:
def cut_find(key, l, start=0):
    mid = len(l) // 2
    if len(l) >= 1:
        if l[mid] == key :
            return f'in position: {start+mid+1}'
        elif l[mid] > key:
            return cut_find(key, l[:mid], start)
        else:
            return cut_find(key, l[mid+1:], mid)
    else:
        return 'Can not find'

print(cut_find(51, li, 0))

# 方法二:
def search(li,key,low,high):
    mid=(low+high)//2
    if key==li[mid]:
        return mid
    if low>high:
        return -1
    if key<li[mid]:
        return search(li,key,low,mid-1)
    else:
        return  search(li,key,mid+1,high)

拆分多重列表元素:

li = []
def all(l):
    global li
    if not isinstance(l, int):
        for i in l:
            all(i)
    else:
        li.append(l)
    return li

汉诺塔:

猜你喜欢

转载自blog.csdn.net/u010359398/article/details/81394361