% m' o: ?9 V5 V$ D4 q) u$ f递归是一种通过将问题分解为更小的同类子问题来解决问题的方法。它的核心思想是:**函数直接或间接地调用自身**,直到满足终止条件。 0 w* v; ?4 O! f* ~ / l1 A; X# O7 }) c6 y0 @ 关键要素9 F5 @% X: i( J8 H8 F6 Z; W; g
1. **基线条件(Base Case)** ! G% R- Q" f% ]: [ - 递归终止的条件,防止无限循环$ H. @6 t$ R2 z4 Z
- 例如:计算阶乘时 n == 0 或 n == 1 时返回 1 . W5 C8 }: H0 J* t+ E. V. s2 h+ r2 f, u. i) C# S
2. **递归条件(Recursive Case)** ' ~: p% e G4 H - 将原问题分解为更小的子问题 ( T/ r, Q) `9 k) J" d, M# O - 例如:n! = n × (n-1)!3 }$ ~( |1 Q. w c* x8 q; I
4 y4 r- r6 L1 z7 r6 \! [
经典示例:计算阶乘: a0 k) R% x, K6 h; y. B
python+ W! a1 j* G9 ?8 G& R! G
def factorial(n):7 h5 i8 b6 s( g6 ~; {# O9 I: X
if n == 0: # 基线条件1 V- {' o7 C, L J
return 1 2 N0 |4 f+ w! p Y else: # 递归条件 1 l4 C; x6 H* f6 p return n * factorial(n-1)9 D$ Y c; i2 Q) A
执行过程(以计算 3! 为例):1 H/ D0 G! N8 C4 ] F5 ?, o M
factorial(3) 5 v- t' I; t7 o3 _ {% {: j! P3 * factorial(2)- Y' f6 O6 O- J
3 * (2 * factorial(1)) 6 v0 K. C# W t) {$ ]# o' {$ u3 ^3 * (2 * (1 * factorial(0)))4 A* B& V, J$ O% d4 J) Z% k# Y
3 * (2 * (1 * 1)) = 6 . S5 q9 I( m; Z & J y6 `3 \, l3 o0 | a 递归思维要点 ! k' y* a7 x+ N2 o* [; w* [+ H1. **信任递归**:假设子问题已经解决,专注当前层逻辑; D! h" O2 D e' h1 h
2. **栈结构**:每次调用都会创建新的栈帧(内存空间) . p4 K2 s) I# I/ |( z0 i& v$ W3. **递推过程**:不断向下分解问题(递)- r' Z8 L" V& t: q* }
4. **回溯过程**:组合子问题结果返回(归)! _. q/ ^3 l R% t
7 P5 H) |, J9 W- M 注意事项 d. _) \" S! S# G/ z必须要有终止条件 0 E7 j! l' r: b a4 D% D: `! q1 M递归深度过大可能导致栈溢出(Python默认递归深度约1000层)2 j! D _! Q8 X. i. N6 \* G
某些问题用递归更直观(如树遍历),但效率可能不如迭代9 y) u1 Q4 I2 y6 ?( L- W9 b7 `
尾递归优化可以提升效率(但Python不支持)) \2 `/ t# w+ i0 X) K8 C
% x& X/ c& {+ z8 j, p3 c+ ^' A: q 递归 vs 迭代/ `7 g2 ~. V+ v# M: a
| | 递归 | 迭代 | & m) O& D+ N. r5 F5 ~|----------|-----------------------------|------------------| 3 A5 S% E' B& c2 E* }| 实现方式 | 函数自调用 | 循环结构 |( Z" ~# }2 }* A) ^) j1 G
| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 |* o' w/ h& F: }2 R8 x+ \* P: c
| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 | ! I+ c' ^% U9 z: L/ t {3 v| 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 | 5 S0 r7 L4 M- {" ~# J* |% V J8 S
经典递归应用场景- l J- ~3 J1 n
1. 文件系统遍历(目录树结构) 1 P9 t1 n! U' w$ }( Z8 F2. 快速排序/归并排序算法( Y, L& J; S; z; p0 @+ p& S, \0 k
3. 汉诺塔问题 4 \! ?6 j6 a+ [- f8 F4. 二叉树遍历(前序/中序/后序)0 q6 f! n, A4 o! @( J
5. 生成所有可能的组合(回溯算法) ! o2 T' A: v) Y2 K* w8 a9 i 1 ?2 w* e% i; f4 b/ m试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒,9 h3 p1 J* j w( g" ]; p
我推理机的核心算法应该是二叉树遍历的变种。8 j" W; d: J# z( {0 o: C; Q1 o+ k
另外知识系统的推理机搜索深度(递归深度)并不长,没有超过10层的,如果输入变量多的话,搜索宽度很大,但对那时的286-386DOS系统,计算压力也不算大。作者: nanimarcus 时间: 2025-2-2 00:45
Recursion in programming is a technique where a function calls itself in order to solve a problem. It is a powerful concept that allows you to break down complex problems into smaller, more manageable subproblems. Here's a detailed explanation:7 ~- f- y$ Z& Y( ~3 C* b- K
Key Idea of Recursion; D) B' a( G$ Z7 T4 X$ ?
* f& t) z7 T M: QA recursive function solves a problem by: : R$ o9 L- `, M& B# |2 C% {/ {+ }, C0 ~2 t3 K/ t
Breaking the problem into smaller instances of the same problem. + N$ }0 @7 M3 ]3 r0 E1 j' g8 K# T8 n0 R3 V& D- }2 |9 K. Z" T! a
Solving the smallest instance directly (base case). " ?- z' T7 R: |- J7 n% y. I% T # B6 z7 R8 B/ ~, V/ Z" |/ W" G, B Combining the results of smaller instances to solve the larger problem.8 y( b4 N) X( g: F4 I0 M, u
( c- [+ o% }! X; l4 _: b0 yComponents of a Recursive Function; `. w6 T! I! S
! i" v& J. J; O0 \3 ]
Base Case: 1 z2 W0 c+ ^4 I8 @( _' L3 @* C( R; _* M
This is the simplest, smallest instance of the problem that can be solved directly without further recursion.! v! B9 o9 Q, V1 t: U
, c9 G M% s# b# K- H/ m It acts as the stopping condition to prevent infinite recursion. % G& W7 S' p' O) k3 [ r3 X9 v! y* O0 \ Example: In calculating the factorial of a number, the base case is factorial(0) = 1. 7 d9 Z+ S; ?- n$ U8 B( ] 5 J$ |2 F% a* D& H8 K2 Z Recursive Case:, A) b6 K$ ^5 t+ G* e; Q7 P. m
) u# n2 j' w7 X% |% l% N" W This is where the function calls itself with a smaller or simpler version of the problem. $ \! P" l7 b+ e, M1 j4 O: E4 |0 ]+ q' ~3 o- E
Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1)., N2 Q) K" U5 y, f
& h4 w9 M& M u2 P6 P- L
Example: Factorial Calculation . u: w8 i! ^; k, n9 E% c/ J* O. H8 F6 Q
The factorial of a number n (denoted as n!) is the product of all positive integers less than or equal to n. It can be defined recursively as:* |" w. {6 W! s! I. t m. R$ m" S
- l5 f. Z1 U* X3 n* b3 j; ]2 Z. E# SHere’s how it looks in code (Python): 6 E( Q, E# T* d8 g' q* hpython * A8 D8 H, G* ]! z6 J9 k* ~) D
4 a5 f* {' M. Ddef factorial(n):* ] P9 V7 G8 }3 g+ ^2 N+ u
# Base case 8 @! E m |& `1 g1 p if n == 0:9 a; X# {, z1 R: [3 m
return 1 0 c# m' T: K' r # Recursive case$ z; f1 o o" k
else: ; t m) Q1 ?) ]8 t% c6 H return n * factorial(n - 1)$ F" K( A( y- m
4 j% f2 F, c7 g, G# y# Example usage & K0 r! a; }- a8 }& {+ jprint(factorial(5)) # Output: 120; h5 @- q! Y8 U2 O
/ w$ k+ Q" h. s+ B. LHow Recursion Works , g* T. v: V! t8 a" b: f1 k% m3 K* u" J! r+ {" e% _1 i
The function keeps calling itself with smaller inputs until it reaches the base case. E$ e4 f+ U& E7 V' J
7 S6 d4 T' o% x6 S. t Once the base case is reached, the function starts returning values back up the call stack.( ^2 E* z* e! `1 X( F0 e& {2 n6 A
- q& X% q$ W. P! i- `; i
These returned values are combined to produce the final result.$ X$ L( z: n" W$ O/ U" E
; b) X m. g A" ]/ o Simplicity: Recursive solutions are often more intuitive and easier to write for problems that have a natural recursive structure (e.g., tree traversals, divide-and-conquer algorithms). 0 v% T9 V' S6 D7 l$ ]6 t& O. C% t( k! w4 x! l
Readability: Recursive code can be more readable and concise compared to iterative solutions.6 W3 j/ l+ O6 M: f
$ Z2 ?! O4 |: q- VDisadvantages of Recursion9 X: ?1 @8 D# z$ S0 w
c- c8 \* H$ X
Performance Overhead: Each recursive call adds a new layer to the call stack, which can lead to high memory usage and potential stack overflow for deep recursion. . b9 G \- |- I1 @0 n4 n7 S7 t0 Y7 J1 A3 y* E u) e" c1 R
Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization).7 [' d4 A+ @4 m" v w: E% S
I; _/ Q) `6 u7 x" P; c
When to Use Recursion _- V, `2 s3 t0 `" N2 @* Z4 q
, m" l" p4 H ^/ M Z4 v
Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort). N, N1 Z9 q; l, J/ G/ I7 Y
( b4 d+ u- b9 E, N
Problems with a clear base case and recursive case. 6 q6 s/ q; o8 ]3 @( Q5 L ( v. {8 q: s( ]Example: Fibonacci Sequence2 V9 q: r* G0 v. e: [2 T5 P
3 I0 J; C$ I$ [& N3 L
The Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones:: D8 r4 G$ B3 \) n" P0 N) N* z
: b7 c- r- j2 y+ D) x9 }6 L
Base case: fib(0) = 0, fib(1) = 1 % F0 j, T0 A! V L$ Z, r& k , k; r3 I# m" X# I6 f Recursive case: fib(n) = fib(n-1) + fib(n-2)8 U" R4 T- S5 |2 ]# N
4 _: S7 c/ t9 G8 \8 H8 bdef fibonacci(n):9 g* B3 i' Q" n1 P
# Base cases ! M5 {/ Y; H+ o1 K1 M6 z+ z if n == 0:% d/ I3 A# f; R& J, @: G2 q
return 0' e2 \5 d, G0 ]( r6 |# ]) R* l
elif n == 1:" n2 y' y% ^- A$ J
return 1! a2 ]2 p! Q) b X" f9 D
# Recursive case , C) U7 H% z" p$ U else:1 f. B0 n5 q3 G8 _/ U; H" w
return fibonacci(n - 1) + fibonacci(n - 2) 7 b3 r* Q( \# c. j. M# I3 o$ g9 J& y5 M$ ]* M) V1 I3 w
# Example usage- y: b _: n8 Q" n g2 r/ `
print(fibonacci(6)) # Output: 8 0 d k9 I& W$ l% t+ f3 V4 a ( r) `2 K$ i, _1 ^Tail Recursion $ @$ J" }! E) d8 Z1 m5 F8 @+ l; C8 X- \+ q' Y( A! z0 F
Tail recursion is a special case of recursion where the recursive call is the last operation in the function. Some programming languages optimize tail-recursive functions to avoid stack overflow, but not all languages (e.g., Python does not optimize tail recursion). : D9 W( t# L# s5 i, ^; e 3 g- {+ m9 i7 V: M7 n, l7 L4 PIn summary, recursion is a fundamental concept in programming that allows you to solve problems by breaking them into smaller, self-similar subproblems. It’s important to define a base case to avoid infinite recursion and to understand the trade-offs between recursion and iteration.作者: nanimarcus 时间: 2025-2-2 00:47
我还让Deepseek 给我讲讲Linux Kernel Driver 现在的开发流程,让一个老同志复习复习,快忘光了。