递归函数 #

一、递归概述 #

递归是函数调用自身的编程技术:

matlab
function result = factorial(n)
% FACTORIAL 计算阶乘(递归实现)

    % 基本情况
    if n <= 1
        result = 1;
        return;
    end
    
    % 递归调用
    result = n * factorial(n - 1);
end

二、递归基本结构 #

2.1 递归三要素 #

matlab
function result = recursive_function(params)
    % 1. 基本情况(终止条件)
    if base_condition
        result = base_value;
        return;
    end
    
    % 2. 递归调用
    smaller_problem = reduce(params);
    partial_result = recursive_function(smaller_problem);
    
    % 3. 组合结果
    result = combine(partial_result, params);
end

2.2 简单示例 #

matlab
% 计算累加和
function sum = cumulative_sum(n)
% CUMULATIVE_SUM 计算1到n的和
    
    if n <= 0
        sum = 0;
        return;
    end
    
    sum = n + cumulative_sum(n - 1);
end

cumulative_sum(5)  % 15

三、经典递归示例 #

3.1 阶乘 #

matlab
function result = my_factorial(n)
% MY_FACTORIAL 计算阶乘
    
    if n < 0
        error('n必须是非负整数');
    end
    
    if n <= 1
        result = 1;
    else
        result = n * my_factorial(n - 1);
    end
end

my_factorial(5)  % 120

3.2 斐波那契数列 #

matlab
function fib = fibonacci(n)
% FIBONACCI 斐波那契数列(递归)
    
    if n <= 0
        fib = 0;
    elseif n == 1
        fib = 1;
    else
        fib = fibonacci(n-1) + fibonacci(n-2);
    end
end

% 优化版本:使用记忆化
function fib = fibonacci_memo(n)
    persistent memo;
    
    if isempty(memo)
        memo = containers.Map('KeyType', 'double', 'ValueType', 'double');
    end
    
    if n <= 0
        fib = 0;
    elseif n == 1
        fib = 1;
    elseif memo.isKey(n)
        fib = memo(n);
    else
        fib = fibonacci_memo(n-1) + fibonacci_memo(n-2);
        memo(n) = fib;
    end
end

3.3 二分查找 #

matlab
function idx = binary_search(arr, target, left, right)
% BINARY_SEARCH 二分查找(递归)
    
    if nargin == 2
        left = 1;
        right = length(arr);
    end
    
    if left > right
        idx = -1;  % 未找到
        return;
    end
    
    mid = floor((left + right) / 2);
    
    if arr(mid) == target
        idx = mid;
    elseif arr(mid) < target
        idx = binary_search(arr, target, mid+1, right);
    else
        idx = binary_search(arr, target, left, mid-1);
    end
end

arr = [1 3 5 7 9 11 13];
idx = binary_search(arr, 7);  % 4

3.4 汉诺塔 #

matlab
function hanoi(n, from, to, aux)
% HANOI 汉诺塔问题
    
    if n == 1
        fprintf('移动盘子1从%s到%s\n', from, to);
        return;
    end
    
    hanoi(n-1, from, aux, to);
    fprintf('移动盘子%d从%s到%s\n', n, from, to);
    hanoi(n-1, aux, to, from);
end

hanoi(3, 'A', 'C', 'B');

3.5 快速排序 #

matlab
function arr = quick_sort(arr)
% QUICK_SORT 快速排序(递归)
    
    if length(arr) <= 1
        return;
    end
    
    pivot = arr(1);
    less = arr(arr < pivot);
    equal = arr(arr == pivot);
    greater = arr(arr > pivot);
    
    arr = [quick_sort(less), equal, quick_sort(greater)];
end

arr = [3 6 8 10 1 2 1];
sorted = quick_sort(arr);  % [1 1 2 3 6 8 10]

四、递归与迭代对比 #

4.1 阶乘对比 #

matlab
% 递归版本
function result = factorial_recursive(n)
    if n <= 1
        result = 1;
    else
        result = n * factorial_recursive(n - 1);
    end
end

% 迭代版本
function result = factorial_iterative(n)
    result = 1;
    for i = 2:n
        result = result * i;
    end
end

4.2 斐波那契对比 #

matlab
% 递归版本(效率低)
function fib = fib_recursive(n)
    if n <= 1
        fib = n;
    else
        fib = fib_recursive(n-1) + fib_recursive(n-2);
    end
end

% 迭代版本(效率高)
function fib = fib_iterative(n)
    if n <= 1
        fib = n;
        return;
    end
    
    a = 0;
    b = 1;
    for i = 2:n
        fib = a + b;
        a = b;
        b = fib;
    end
end

五、尾递归 #

5.1 尾递归概念 #

尾递归是递归调用在函数末尾的递归:

matlab
% 普通递归
function result = factorial(n)
    if n <= 1
        result = 1;
    else
        result = n * factorial(n - 1);  % 递归后还要乘n
    end
end

% 尾递归形式
function result = factorial_tail(n, acc)
    if nargin < 2
        acc = 1;
    end
    
    if n <= 1
        result = acc;
    else
        result = factorial_tail(n - 1, n * acc);  % 尾递归
    end
end

5.2 尾递归优化 #

matlab
% 累加和尾递归
function sum = sum_tail(n, acc)
    if nargin < 2
        acc = 0;
    end
    
    if n <= 0
        sum = acc;
    else
        sum = sum_tail(n - 1, acc + n);
    end
end

六、递归应用场景 #

6.1 树遍历 #

matlab
function traverse_tree(node)
% TRAVERSE_TREE 遍历树结构
    
    if isempty(node)
        return;
    end
    
    % 访问当前节点
    disp(node.value);
    
    % 递归遍历子节点
    for i = 1:length(node.children)
        traverse_tree(node.children{i});
    end
end

6.2 分形图形 #

matlab
function draw_fractal(x, y, size, depth)
% DRAW_FRACTAL 绘制分形
    
    if depth == 0
        return;
    end
    
    % 绘制当前图形
    rectangle('Position', [x, y, size, size]);
    
    % 递归绘制四个角
    new_size = size / 3;
    draw_fractal(x, y, new_size, depth-1);
    draw_fractal(x + 2*new_size, y, new_size, depth-1);
    draw_fractal(x, y + 2*new_size, new_size, depth-1);
    draw_fractal(x + 2*new_size, y + 2*new_size, new_size, depth-1);
end

6.3 组合问题 #

matlab
function result = combinations(arr, k)
% COMBINATIONS 生成组合
    
    result = {};
    
    if k == 0
        result = {{}};
        return;
    end
    
    if k > length(arr)
        return;
    end
    
    % 包含第一个元素
    sub_comb = combinations(arr(2:end), k-1);
    for i = 1:length(sub_comb)
        result{end+1} = [{arr(1)}, sub_comb{i}];
    end
    
    % 不包含第一个元素
    sub_comb = combinations(arr(2:end), k);
    result = [result, sub_comb];
end

combs = combinations({'a', 'b', 'c', 'd'}, 2);

七、递归陷阱与优化 #

7.1 栈溢出 #

matlab
% 可能导致栈溢出
function result = deep_recursion(n)
    if n == 0
        result = 0;
    else
        result = 1 + deep_recursion(n - 1);
    end
end

% deep_recursion(100000)  % 可能栈溢出

% 优化:使用迭代
function result = deep_iterative(n)
    result = n;
end

7.2 重复计算 #

matlab
% 斐波那契递归有大量重复计算
% 使用记忆化优化
function fib = fib_memo(n)
    persistent memo;
    
    if isempty(memo)
        memo = containers.Map();
    end
    
    if memo.isKey(n)
        fib = memo(n);
        return;
    end
    
    if n <= 1
        fib = n;
    else
        fib = fib_memo(n-1) + fib_memo(n-2);
    end
    
    memo(n) = fib;
end

7.3 限制递归深度 #

matlab
function result = safe_recursion(n, max_depth)
    if nargin < 2
        max_depth = 1000;
    end
    
    if n <= 0
        result = 0;
        return;
    end
    
    if max_depth <= 0
        error('递归深度超限');
    end
    
    result = 1 + safe_recursion(n - 1, max_depth - 1);
end

八、最佳实践 #

8.1 选择递归或迭代 #

matlab
% 递归适用:
% - 问题自然递归定义(树、图)
% - 代码更清晰
% - 递归深度可控

% 迭代适用:
% - 性能要求高
% - 递归深度大
% - 内存受限

8.2 添加终止条件检查 #

matlab
function result = safe_recursive(n)
    % 检查输入
    if n < 0
        error('n必须非负');
    end
    
    % 基本情况
    if n == 0
        result = 1;
        return;
    end
    
    % 递归
    result = n * safe_recursive(n - 1);
end

九、总结 #

本章学习了:

  1. 递归概念:函数调用自身
  2. 递归结构:基本情况、递归调用、组合结果
  3. 经典示例:阶乘、斐波那契、二分查找、汉诺塔、快排
  4. 尾递归:递归调用在末尾
  5. 应用场景:树遍历、分形、组合问题
  6. 优化技巧:记忆化、限制深度

下一章将学习MATLAB的绘图功能。

最后更新:2026-03-27