数据结构与算法——自学总结之递归和分治思想

首先来认识一下递归

递归

是指在函数自身内部调用自己,好理解,自己调用自己嘛,然后它包含两个方面,一种是递归条件,一种是基准条件

基准条件

这是递归的终止条件,当满足基准条件时,函数不再调用自身,从而避免无限循环(就是一个限制循环的终点线)

递归条件

这是函数调用自身的部分,用来逐步解决问题。(这是递归运行的发动机)

例子

阶乘(factorial)是递归的经典示例。阶乘函数的定义是:

n! = n × (n-1)!(递归条件)

0! = 1(基准条件)

def factorial(n):
    if n == 0:
        return 1  # 基准条件
    else:
        return n * factorial(n - 1)  # 递归条件

解释:

基准条件:当 n 等于 0 时,函数返回 1,这是递归的终止条件

递归条件:函数计算 n! 时调用 factorial(n - 1) 来计算 (n-1)!。这个调用会继续进行,直到达到基准条件

斐波那契数列

斐波那契数列的定义是:

F(n) = F(n-1) + F(n-2)(递归条件)

F(0) = 0F(1) = 1(基准条件)

def fibonacci(n):
    if n == 0:
        return 0  # 基准条件
    elif n == 1:
        return 1  # 基准条件
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)  # 递归条件

解释:

基准条件:当 n 等于 01 时,返回相应的值。

递归条件:函数计算 F(n) 时调用 fibonacci(n - 1)fibonacci(n - 2),将问题拆解为更小的子问题。

递归的优缺点

优点:代码简洁:递归可以使代码更简洁、更具表达力,特别是在处理复杂数据结构如树和图时。

缺点:性能问题:递归可能导致大量的函数调用,特别是在处理大量数据时,这可能导致性能下降或者栈溢出。可读性:对于复杂的递归,可能会使代码难以理解。

这些东西都还好理解,那么接下来来介绍一下分治思想

分治思想

分治思想就是把问题拆分为几个小问题,把这些小问题解决的解合并得到原来问题的解。

基本步骤

分解:将原始问题分解成若干个规模较小的子问题。通常,子问题是原问题的一个子集或缩小版。

解决:递归地解决这些子问题。如果子问题足够小,直接解决它们;否则,继续应用分治策略。

合并:将子问题的解合并成原始问题的解。

经典示例

下面介绍两种算法

1. 归并排序(Merge Sort)

其核心思想是利用分治策略将一个大数组分解成多个小数组,排序这些小数组,然后将它们合并成一个有序的大数组。(大数组分成小数组,再合并成大数组)

过程:分解:将数组递归地分割成两半,直到每个子数组只有一个元素(已排序)(大数组分成小数组)

合并:将这些小数组合并成一个有序的大数组。合并操作涉及将两个已排序的子数组合并成一个更大的排序数组。(小数组合并成大数组)

python展示

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left_half = merge_sort(arr[:mid])
    right_half = merge_sort(arr[mid:])
    
    return merge(left_half, right_half)

def merge(left, right):
    sorted_arr = []
    i = j = 0

    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            sorted_arr.append(left[i])
            i += 1
        else:
            sorted_arr.append(right[j])
            j += 1

    sorted_arr.extend(left[i:])
    sorted_arr.extend(right[j:])
    
    return sorted_arr

分解merge_sort 函数将数组分成两半,然后递归地对每一半进行排序。

合并merge 函数将两个已排序的子数组合并成一个排序好的数组。

2. 快速排序(Quick Sort)

其核心思想是选择一个“基准”元素,然后将数组分成两个或者三个子数组,一个包含比基准小的元素,另一个包含比基准大的元素,然后递归地对两个子数组进行排序。(简单来说就是给个标准,然后把整个数组分成两部分,一个比标准高,一个比标准低,或者一个等于标准,然后通过递归排序)

过程:

分解:选择一个基准元素,将数组分成两个部分:小于基准的元素和大于基准的元素。

解决:递归地对两个子数组进行排序。

合并:快速排序不需要显式的合并步骤,因为它在原地进行排序。

def quick_sort(arr):
    if len(arr) <= 1:
        return arr

    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    
    return quick_sort(left) + middle + quick_sort(right)

分解:选择基准元素并将数组分成三个部分(小于、等于、大于基准)

解决:递归地对这三个部分进行排序。

合并:通过拼接已排序的部分得到最终结果。

以上提到的两种排序算法后续也会慢慢介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值