. i( I' C! Y$ c" v递归是一种通过将问题分解为更小的同类子问题来解决问题的方法。它的核心思想是:**函数直接或间接地调用自身**,直到满足终止条件。 7 q g. {8 \% f8 d1 w" c% p: R - ]$ v% K! O/ } 关键要素0 A) T2 S0 W6 K' B. j) ^
1. **基线条件(Base Case)**: S" A' A9 @7 m6 s
- 递归终止的条件,防止无限循环 - ^ a3 ?3 |5 r - 例如:计算阶乘时 n == 0 或 n == 1 时返回 1% ` g1 ]% t9 t& x( ?+ j9 W Y
& J6 h V* W# n% A3 p- o# o2. **递归条件(Recursive Case)** ' J0 y3 U4 X1 v' z- a1 L - 将原问题分解为更小的子问题 + l0 x6 x- g. Q' t# L# W - 例如:n! = n × (n-1)! $ f* d# M$ Q# E: M1 S a2 z% j " w$ [5 j4 O/ d( f& N" z: b$ M 经典示例:计算阶乘. b8 U! L* _: s3 S# H
python * |" d& g& ]8 y+ i3 R' vdef factorial(n): , T/ r, f/ m0 ?5 ` if n == 0: # 基线条件 * z$ [7 D! p+ l% ~% g G return 10 f8 q$ m3 M$ ?% H$ x5 X
else: # 递归条件8 O- ]: c, _9 P& s
return n * factorial(n-1)/ `% W. V# f, Q5 ~8 |5 V; r
执行过程(以计算 3! 为例):% ?% N; \7 W |6 b2 D0 C v
factorial(3)) b+ r5 E% W4 L5 Y* W4 ?
3 * factorial(2) / C- k0 R4 @ ~! b8 X+ k. f% f/ m3 * (2 * factorial(1))8 q) ?4 K* U7 q, N- ^1 M
3 * (2 * (1 * factorial(0)))4 m/ `; R) \; {* s1 F& P+ y
3 * (2 * (1 * 1)) = 6 M, |/ ?. P- \0 y , n$ U! J3 W4 N) `) Y& I 递归思维要点6 i, C: T8 Q/ @: e
1. **信任递归**:假设子问题已经解决,专注当前层逻辑 5 S1 X; x) ?6 X; P. F2. **栈结构**:每次调用都会创建新的栈帧(内存空间)& S8 P6 F: @4 B
3. **递推过程**:不断向下分解问题(递) 3 T2 f5 ]* }" P6 \2 P, t4. **回溯过程**:组合子问题结果返回(归); l1 R4 Z2 E" s; w8 m
4 i5 C1 ~7 W* L/ U 注意事项2 q5 f% A' k( E9 Q; r
必须要有终止条件1 n; K2 h# @6 l
递归深度过大可能导致栈溢出(Python默认递归深度约1000层) 1 k# X5 Q5 {% l3 D. J某些问题用递归更直观(如树遍历),但效率可能不如迭代 " t: C4 ], E- T A5 r% s尾递归优化可以提升效率(但Python不支持) - M9 {' B- ?. w( r3 c# |+ ~: D+ Y$ A. O" [; A s
递归 vs 迭代7 [ w% G+ _4 p$ j/ V
| | 递归 | 迭代 | 1 c# q& k3 Y: O% ^2 o1 R' m B* W|----------|-----------------------------|------------------|" I9 H h& k% Y5 s9 L7 p
| 实现方式 | 函数自调用 | 循环结构 |# \! e+ Y2 }7 r1 O$ w! y/ T, K% }2 C
| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 |5 T' h" D. l1 g8 Z
| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 |5 q/ L! J T* P& _9 J# K, N( h
| 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 | ' k# j9 f1 s6 D, M% P* P 0 g0 W+ \# {5 p; }5 Z 经典递归应用场景 * Y/ Q( a7 q5 d7 l: ?. f& g ? u1. 文件系统遍历(目录树结构), G$ l) b) Y# B9 ^: m
2. 快速排序/归并排序算法0 u, x/ p! ~! Y9 r. ~
3. 汉诺塔问题 1 c* z7 x) }+ k5 \8 A' F) v& S/ \4. 二叉树遍历(前序/中序/后序) ' Z, }: f% b* h" I5. 生成所有可能的组合(回溯算法)% i: b& I' G7 a6 \
9 S4 ^2 Y6 n5 d试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒, 2 d7 H' \9 ]' K" B4 }- j+ p+ @0 [我推理机的核心算法应该是二叉树遍历的变种。 4 ^6 r. ~; A7 Y; H1 V; j( c另外知识系统的推理机搜索深度(递归深度)并不长,没有超过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:' B% K, i( m* l. j+ I* o2 n
Key Idea of Recursion+ \% ^ v, L0 ]5 l8 g7 b8 ?1 s
, Z6 V7 e# }' E* i6 ^4 eA recursive function solves a problem by:; s6 W+ k8 I5 L" P( ]3 Y& I! u" F
. v' G8 W5 }) _' U$ o0 S7 t
Breaking the problem into smaller instances of the same problem.9 C3 h5 j. W Y5 f* k! y" J! m7 ]
7 z3 M5 J6 h% I& {+ k) |, ^ H; h
Solving the smallest instance directly (base case).' g6 X! R n+ l. a! A
3 r: f8 A. S# x' Y Combining the results of smaller instances to solve the larger problem.3 d; ?& P2 e x7 P
, m: J& O/ @* DComponents of a Recursive Function , f+ E" L: x+ ^6 M" ~; M- C: E ?! K% ?6 y+ Q, i) J1 S [
Base Case:/ l6 F) w5 n: o# g
. g$ p" Z% ~, i$ p) {( B* B3 [
This is the simplest, smallest instance of the problem that can be solved directly without further recursion. ) y0 \0 l: R$ s+ k3 c) E / V! V* X7 i: L% k It acts as the stopping condition to prevent infinite recursion. 3 E! {3 T, F6 h6 L7 P3 ]5 R( B' r( M; p g+ [" L5 | y
Example: In calculating the factorial of a number, the base case is factorial(0) = 1.. R. | i c& o8 k6 g
1 d- y3 g2 h$ y: A1 d Recursive Case: 4 o8 c! W5 h& T X9 b4 C. x/ [8 L 1 O1 _1 w; P0 j0 Y) f; s This is where the function calls itself with a smaller or simpler version of the problem.1 t; B. b0 w6 w
+ r1 H2 U: m/ U4 S4 d Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1).& ^/ z6 S3 u8 s+ L: Z9 Y8 T) n
0 Q4 U% X% [) h1 d4 k2 d4 O
Example: Factorial Calculation7 r" @8 d0 e+ M e% y% |
& g: l% I8 V# c$ a2 @; |1 y3 c$ ?
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: ( }6 C* ^; {5 G* P4 ^: A) E$ I7 \4 d# d* W
Base case: 0! = 1+ I( V/ S& f2 O1 I
9 y& l$ S8 V* p0 }# L' o" @ Recursive case: n! = n * (n-1)! 5 T' w# e. [, o! I* k) ~ 9 m0 t w9 _! ^% RHere’s how it looks in code (Python):3 }/ g, W2 A' U. R
python8 y1 L: ?3 I. d/ Z3 V
1 U z4 S) i7 I$ G8 z$ u+ ?
, J0 m+ ^+ ^7 R, A7 s3 }def factorial(n): : z* F+ C$ Y {7 |0 y7 K # Base case, s& _, \0 F# {. b9 g
if n == 0: u1 @0 i7 w- t/ L
return 12 A3 @, o& u$ X# H3 i. m" d
# Recursive case * x0 Y, A r+ |. o K( m) r else:; ~/ G) P( `$ |
return n * factorial(n - 1) 4 X2 A; f7 M( M9 X \* G 8 v/ z( J! F" X' ~7 e6 R# Example usage5 U5 m. r5 B8 H+ D
print(factorial(5)) # Output: 1205 l6 t5 b2 Y- j6 O; g( \4 t# M
4 [' k( r$ E: R( rHow Recursion Works, y, k! A _, y, q8 f
" `; L/ H+ p0 }; N' ] The function keeps calling itself with smaller inputs until it reaches the base case.! x- f a/ o1 i; W
; b; j+ w: ~0 u, N: C! s2 J% w2 f$ I
Once the base case is reached, the function starts returning values back up the call stack. 3 e: R" ?. E" f5 r4 i- a( J: b3 ] 3 e- J, f) U O& C These returned values are combined to produce the final result. 5 q0 w* h+ o5 A. \ l# ]4 u! n% | {3 \9 I) wFor factorial(5):' }% C" E) G* I( L$ r# ^7 R
# I( J( [- V' E( g! a$ a
1 f' }1 K. r: `/ z8 U6 c- _+ Zfactorial(5) = 5 * factorial(4)' j {" L4 ^$ T
factorial(4) = 4 * factorial(3)7 J& K/ h& }! D* N6 H, b( k
factorial(3) = 3 * factorial(2)+ @8 X7 K4 h) n
factorial(2) = 2 * factorial(1) q: N6 K* D8 y# Q4 p
factorial(1) = 1 * factorial(0) i- L H( h1 e. ^0 ]# F
factorial(0) = 1 # Base case / }! m6 Y5 M: ?) Y K9 F4 l1 L# |8 M1 C7 [
Then, the results are combined:" K, O$ h+ N$ h1 f4 k0 i6 ~
) C' W( T/ h$ I; w+ N' H* A! i
) S: i3 x3 I) F, p" R8 b
factorial(1) = 1 * 1 = 1" x9 q$ O6 }+ ?) ]
factorial(2) = 2 * 1 = 28 j, ^: [" V9 ~) Z$ b
factorial(3) = 3 * 2 = 62 F3 ?. ?' F* r/ I% y0 H
factorial(4) = 4 * 6 = 243 O- V U6 q6 c
factorial(5) = 5 * 24 = 120 5 g, h( E- d/ K8 X+ ^# @1 r/ J - p8 |2 {' F$ i6 JAdvantages of Recursion" [( {% ^& A9 o, Q4 R, K+ _5 _
& ~, k& W' u9 e3 U2 ?3 ~8 p 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). 8 T' I7 |+ F* R & P% Y! E2 [7 W3 ]; \ Readability: Recursive code can be more readable and concise compared to iterative solutions.$ w8 ^6 c# D1 E5 D F* ]( w* F
! {1 Y8 W" C# d5 _2 H
Disadvantages of Recursion # \: S, r( p R: X6 V( l( b( Z& j/ k8 Z% }5 d! s# 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.1 U# F4 n, ^% o4 _4 S& a
% B$ R: O7 x! k$ W8 F& X- W) Y6 Z Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization).% |! H t4 |8 s- ?
+ C; q! `0 [4 U+ c w2 n
When to Use Recursion# X) V8 b$ w" ^+ O$ s
: Q5 K4 D: z9 W0 h2 W$ S6 }
Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort). / P" p) i. D( N- E . s4 h8 z6 b) K5 V& o0 r7 p$ u Problems with a clear base case and recursive case. 7 \2 o' D9 {( }+ c8 X' ^1 \! y! j& E: [ ' _: V4 Y h; V( z- b2 I- CExample: Fibonacci Sequence, Q! `: B3 y U# v5 X# D+ `) {
- s. O4 a, H, ], X$ \6 aThe Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones: 7 t* R5 X, u3 f% j! `+ ~( t # k* O& }0 x- ? Base case: fib(0) = 0, fib(1) = 1 6 T- E: U3 D% S7 i2 a, }$ G, P* _. u3 Q
Recursive case: fib(n) = fib(n-1) + fib(n-2): f7 e, S5 {3 b8 r4 B6 y
7 p# Z5 ^, `0 z0 a8 ~python 7 T8 ]7 ~. y- o; p$ t) U* g5 F 1 Y8 T8 W- P8 \& |2 r ' i; l8 X8 L# D' X$ kdef fibonacci(n): 0 ^, w+ B$ W. ^% h1 _8 V! A9 t # Base cases; x, s1 O/ M+ o9 P d3 i
if n == 0:9 T& `$ p0 M: C' v4 [( {+ c, [
return 0 6 ]0 |' C$ I6 X. F1 T elif n == 1:6 { T8 {7 m! T4 [
return 1 s' P. E9 I& k7 z$ p+ E9 o; [
# Recursive case. z1 X k, ?6 E
else:: F$ r- J' ?. V) {
return fibonacci(n - 1) + fibonacci(n - 2) ( Y: v6 k5 m( O/ b( V7 h ) F6 e- [1 _5 U* L6 u# Example usage 9 G9 B2 z$ r6 B* Cprint(fibonacci(6)) # Output: 80 T& Q, Z! Z: ` M0 w$ H! i
4 u; V: u4 H6 V
Tail Recursion7 O6 a- O: o R7 ], a
0 G. P: W) i q, I) [8 vTail 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)." a2 }8 f4 f2 q' h
. S8 X" y$ D6 p- p$ d
In 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 现在的开发流程,让一个老同志复习复习,快忘光了。