* v, e, q# g! V: } 关键要素 " {# ^# }. W5 N) Q1. **基线条件(Base Case)** g" L7 P; `1 k y! I - 递归终止的条件,防止无限循环5 c' u$ E: H3 b' S
- 例如:计算阶乘时 n == 0 或 n == 1 时返回 1 9 C1 d; J. b3 T5 R+ `- I; ~( |# V1 u4 P# h: E4 D3 ^+ M, U9 o
2. **递归条件(Recursive Case)**8 Z& }2 [3 d. @: f! y2 F
- 将原问题分解为更小的子问题 " L( P/ w! ^$ X/ f - 例如:n! = n × (n-1)! ' A* z9 V- U9 X" @0 q$ t4 j4 E, Z2 O! {5 w# V' N9 M; a
经典示例:计算阶乘 1 X( j: ^, x; O4 [1 O6 Q7 c( dpython ) u9 u7 R* ]% k1 C; J. Adef factorial(n):% `; I1 s' ]8 {7 C( u. Q
if n == 0: # 基线条件0 W2 F! @+ T9 M. M2 U
return 1 7 Y; F" l# U) }4 D9 r- d else: # 递归条件 ; J: q, b# K# n' z! S9 z+ R return n * factorial(n-1) , \% {2 Y; X. b: H$ C执行过程(以计算 3! 为例):# X7 T6 A* E2 Y3 s
factorial(3) 5 U4 W+ c' L0 v! I) p# i. H, v3 * factorial(2) / [* ?' f' `% R n- T2 P0 D3 * (2 * factorial(1))- O( o& A. ?- A% u! _ R/ i
3 * (2 * (1 * factorial(0)))+ K$ _& |% w+ x2 o& l9 f5 q
3 * (2 * (1 * 1)) = 6 ! C2 e) N- R3 y S) M( K 7 U$ E4 m& n x, i( h6 c2 T' H8 o% O 递归思维要点4 d$ V. ~1 f E6 {# u5 D
1. **信任递归**:假设子问题已经解决,专注当前层逻辑 ) _% E& x, O5 M7 P2. **栈结构**:每次调用都会创建新的栈帧(内存空间)5 h7 r- H) V# s7 B! n( w) z. d: |
3. **递推过程**:不断向下分解问题(递)7 Q- b" M7 q; [# }+ Y
4. **回溯过程**:组合子问题结果返回(归) 1 d' F: B! b( x8 a, s3 ~0 z9 h, M2 p$ m( C6 J& r
注意事项9 W1 h+ ^5 o( |7 G2 H
必须要有终止条件 ; D" w( u; h" S6 a' s: f; ]递归深度过大可能导致栈溢出(Python默认递归深度约1000层), [) U; a( @2 z3 }+ B( z( C! q
某些问题用递归更直观(如树遍历),但效率可能不如迭代2 b: H) ?: @1 S: G- S9 N, u
尾递归优化可以提升效率(但Python不支持) 9 d5 z4 i1 O- w+ d4 B, a- x1 m g. x! _& B j; \
递归 vs 迭代- k. r& U. W/ e
| | 递归 | 迭代 |% v; U" q, X, E U, i3 m5 T
|----------|-----------------------------|------------------| 8 L9 Y" W- n& Y0 B; Z. ]| 实现方式 | 函数自调用 | 循环结构 |& i5 [6 j" @. b! y. @) B @
| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 | V7 ^. x$ G6 S
| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 |( w2 B! h" ]' Y6 B- ^) y4 V
| 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 | 2 j) Q3 O' G9 n( W8 e: F 9 W* h6 ~: V$ M! h. n z 经典递归应用场景 ( Q" V8 T: T& U9 Y5 I1. 文件系统遍历(目录树结构)6 S& k! u+ t- ]8 E1 v, Y
2. 快速排序/归并排序算法; ^& e. g! a: k& {+ \
3. 汉诺塔问题& d; i! E7 m) E H' w S
4. 二叉树遍历(前序/中序/后序)% m. J4 R2 ? I5 O2 s9 {
5. 生成所有可能的组合(回溯算法), h6 @$ \- q2 C5 r. F" z
& R5 P3 u! `! s+ q& X试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒, : w: w9 {7 m$ ]# b2 e! p我推理机的核心算法应该是二叉树遍历的变种。- }- o+ A& w$ B/ F$ E) j
另外知识系统的推理机搜索深度(递归深度)并不长,没有超过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:8 U1 V5 }! m* z6 Y9 k# i6 C7 h
Key Idea of Recursion/ i! m6 @- M6 m
, Z" b% _# ^3 N3 y1 M
A recursive function solves a problem by:$ v" h# _: w2 w
6 ~# f3 j a' ~; j# l Breaking the problem into smaller instances of the same problem. % X6 }+ E: K1 w7 @0 N" h1 w$ x" [9 l$ {8 D
Solving the smallest instance directly (base case). ) x; j9 w8 J' B# S1 G" i9 `7 O% s' `/ |
Combining the results of smaller instances to solve the larger problem. : `; P: s2 G; \; C/ q; ~2 K" z' x. V. Z( o8 _* l
Components of a Recursive Function / D" U) i) A# d: U6 _- V- K [6 j& Z, }8 w8 Q Base Case:# ?) V/ c v2 y; X' b( z! m: \
4 K- k8 K: ~$ e) n
This is the simplest, smallest instance of the problem that can be solved directly without further recursion.+ o+ f8 ?8 F8 B& x! R5 E! r
: G% s, b u! R/ m0 `' I% Y It acts as the stopping condition to prevent infinite recursion. 5 D" [+ x( l" ^# h8 w& s / `& @' \6 e( E& |0 @ Example: In calculating the factorial of a number, the base case is factorial(0) = 1. ; s5 G0 d, T7 w9 }& U( @+ U% F3 H2 `5 I- x; K
Recursive Case: ( }9 T g, N' Y: c2 t9 Z# i2 H( x! M# n/ e' }3 c+ v7 g ~! l6 X
This is where the function calls itself with a smaller or simpler version of the problem.7 K( b' {1 z; b- e
& B# J, I6 G, ?+ Q) r' p
Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1). . H9 P. l0 W. a0 k; g2 C3 F7 |3 m0 U6 } C w/ u
Example: Factorial Calculation 1 U& R; Q2 H2 d, i; u- h. B/ f" o9 z: ~% G1 V7 u# z; ~
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: ( s7 ~0 R3 j3 T, V7 Y0 s- @6 \* H( a+ Z2 X, E* w
Base case: 0! = 1) c4 y7 q) m7 O5 L. r) d
2 f3 R$ e7 A4 f
Recursive case: n! = n * (n-1)!) D. X# U( x: h! I- K: I# N3 G& [
# U' j9 H: o: n0 D
Here’s how it looks in code (Python): ! C- j/ l" n/ B. }; V3 dpython , W* [/ o% e* u5 {. ~* L7 v. l: w6 L, ~% V" _: |, f0 `
. r- _. E; S w; o
def factorial(n): 8 g5 m4 j9 @1 C6 ? # Base case8 u+ A4 v" X. e T& ^
if n == 0:7 t( F2 u; ?9 @" K& t1 U
return 13 ?% M. T: Q4 H
# Recursive case ; h# m3 c; n$ J3 I$ k* K5 d9 T% Y else: ) T7 r: N2 T3 t7 \! V/ y/ i return n * factorial(n - 1) : ]5 E' ]2 ^. q; n5 |$ e) v6 y" \& v& m% n5 M+ v- j: T
# Example usage % C/ U4 M. l+ ?5 _4 Vprint(factorial(5)) # Output: 120# L: @+ a' x% X( A1 |
5 P X) E/ h* Y& L& Q% j4 s6 p
How Recursion Works " J, U3 ^5 v2 I6 N7 P. j 5 K; Y! S' a8 B, B- K4 f The function keeps calling itself with smaller inputs until it reaches the base case. ! @6 \( ]( H$ G2 M' M% D - e8 H+ y4 P* G Once the base case is reached, the function starts returning values back up the call stack.3 O- e+ M3 F9 [7 A
9 L: R$ M" F! m3 b
These returned values are combined to produce the final result.8 C" T; F2 s( X* U8 w1 e3 n
- @: R* ]* A% F h% E/ S/ U4 F
For factorial(5): " E; Y8 h3 X5 H( w. t% Z $ Y0 _0 D! @0 t4 _+ ~7 n, d5 }# O ]+ f+ t9 Z E
factorial(5) = 5 * factorial(4) 5 V: e$ @* ^3 I" ]5 {) k) ffactorial(4) = 4 * factorial(3)$ d: D4 d2 D' x; e- [
factorial(3) = 3 * factorial(2)( y+ B$ z P: v; k; c9 U; j3 D3 \
factorial(2) = 2 * factorial(1) ; p% ^6 G& R! E9 X4 s# ]' M! E& _factorial(1) = 1 * factorial(0) . M$ C4 y* X; vfactorial(0) = 1 # Base case . o8 K: L, v/ q% b" H/ O5 P+ b, |' w, b. F1 j& h! l. T
Then, the results are combined: ; i+ j1 u5 c: h7 {& [ 2 L3 ] N! F' V) T & H5 @6 y+ p" ]% B! Zfactorial(1) = 1 * 1 = 1$ e: @% J \+ h
factorial(2) = 2 * 1 = 2 y; I' \; G0 l, m9 L
factorial(3) = 3 * 2 = 6 " f' L2 A8 X9 S% Sfactorial(4) = 4 * 6 = 24 % E+ G' d! k- ~/ R/ X( |9 y Bfactorial(5) = 5 * 24 = 120 ( e! f* Z: X1 Y& ?2 X! u' x. \# B3 r7 E( C8 K1 k/ t" A
Advantages of Recursion$ }' }5 ]+ G$ t2 Q0 c2 V. I5 V- p
9 a0 ]. e) L# X* q; u S5 Z
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).% [. ~* B6 ^9 E$ |
( H2 @2 z6 }7 K6 ~3 _
Readability: Recursive code can be more readable and concise compared to iterative solutions. - t- Q9 X& ?3 V6 M ( d4 i3 M" G' ~2 sDisadvantages of Recursion 8 S |4 w+ j- B4 V/ W% j- `+ _: t 6 `; J' x1 Z; E2 ]% f! N- O: D3 V 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. 8 g3 v4 t% y" m' b9 R% x# Y3 r& p0 |* {. i R( }
Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization).2 y1 |; E1 h6 h# ^$ S5 D' u( d
) H: ^ h% L6 S/ m; s
When to Use Recursion : z% R ^2 r5 |3 c& v + \! u9 v% _) J$ n3 a- F. k6 I$ j Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort).- h7 V% d" y8 P
7 I1 ]/ w3 k+ d' Q# ^
Problems with a clear base case and recursive case.; Y) U0 V% W0 ]# r |
$ I/ H% O: `. `# ^/ O
Example: Fibonacci Sequence9 t W6 L' c8 Y5 A
: T# ~ f, h0 J3 B! ~% G: \
The Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones: & r5 v% [$ M* S1 z. p K + h! S! U7 C' [$ [1 X7 F Base case: fib(0) = 0, fib(1) = 1 7 d5 k/ E/ [ r! { . ]( `+ h# y6 y" V- C" F: } \ Recursive case: fib(n) = fib(n-1) + fib(n-2) 2 n3 w9 ?. t Y( T 4 ?( F# n# G# R cpython. l ^; R% W: A: N+ j$ }
9 P( S8 h( u& N: P + h% I) A0 t& F2 R/ q) \def fibonacci(n): / x! p# S2 p6 L( t; ]5 l # Base cases 6 |" @# S- `* `, |) ^ if n == 0: 4 _- n7 m3 j3 q& I2 Z( L return 05 e3 y D7 i, w8 l/ X
elif n == 1:0 a1 ~3 U8 y2 ?5 k+ E! a& t3 C
return 1 j& F6 s3 \% |0 d& t9 x5 Z1 H$ G
# Recursive case7 U8 s. ^1 [4 v `, \' P7 Q. o
else:* t9 _" ^$ C" a& C9 o9 i
return fibonacci(n - 1) + fibonacci(n - 2) / ?' d: T' D+ ]$ e8 Q, @: |3 o P1 V/ F
# Example usage a" E$ [( w: ]8 F$ }8 @( jprint(fibonacci(6)) # Output: 8- n* R" y* P6 E1 v7 `: W
$ J( R: D1 i# h( y: }/ y9 R9 ITail Recursion 5 X6 e: v1 k0 J* A: }% n) l" B0 I9 B/ f: N
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). 6 _+ K' E! }: B7 Z$ S, E- z- u1 |0 b B A! R& v
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 现在的开发流程,让一个老同志复习复习,快忘光了。