& [* h+ ]8 @# g& N 经典示例:计算阶乘+ _5 B1 C6 K; \: B- }9 D8 C8 X
python0 m6 H6 h+ [3 O/ x# V3 B
def factorial(n):* \) p5 D4 u8 H' c6 S
if n == 0: # 基线条件9 n* |) ?, L& j! b
return 1 ) C, I7 r! K* o* w' u# M* o else: # 递归条件) q# }0 ~( \4 Z+ j; E1 |
return n * factorial(n-1)8 v+ d$ Z& o# i
执行过程(以计算 3! 为例): ! m$ Z9 S$ w1 S3 nfactorial(3)3 A: X: s; a9 ^0 s8 o
3 * factorial(2) 2 l* D; H* X0 b$ ~4 a) h/ t6 b* B3 * (2 * factorial(1))0 C; {( y p1 E. Y5 N
3 * (2 * (1 * factorial(0))) ; L8 {2 C+ I9 W8 o% D3 * (2 * (1 * 1)) = 6" _5 Z4 }" K' e
7 C4 m+ d$ j, G9 a, I
递归思维要点1 M% s! {4 ]6 Q8 l
1. **信任递归**:假设子问题已经解决,专注当前层逻辑 % j+ P; [6 M4 F: b+ h7 h( B# Q2. **栈结构**:每次调用都会创建新的栈帧(内存空间)# _# ^0 d E I
3. **递推过程**:不断向下分解问题(递)8 @ |% h7 ]2 p, L9 N) t
4. **回溯过程**:组合子问题结果返回(归); v2 z& i) f1 e. n2 W8 ~* a
4 F2 u6 O8 c, y5 Q& ?
注意事项 9 x2 j( X- Y9 p. |) B必须要有终止条件/ E5 G1 Y3 \* ]
递归深度过大可能导致栈溢出(Python默认递归深度约1000层); D! t* i5 h: c5 d5 a, ^: ~* w
某些问题用递归更直观(如树遍历),但效率可能不如迭代! ?6 o4 O7 b8 _: M
尾递归优化可以提升效率(但Python不支持) 5 A- @6 N& `, J% @4 o( x3 Q7 P8 B; G9 V( F6 p1 k7 B
递归 vs 迭代- c- t0 p/ _3 f0 Q! V
| | 递归 | 迭代 | ) H6 T4 O& F B; E% B|----------|-----------------------------|------------------|" L: S1 ^& U. E: y
| 实现方式 | 函数自调用 | 循环结构 |$ R6 h! g" _- q8 W
| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 | % u9 A" a' w& D! T/ Z" O0 L| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 | 4 W+ x: d0 a. e| 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 | , t+ N8 W& M" [6 G' A ) |' g3 E+ |8 t- b 经典递归应用场景 O: b# [- Y( n+ d- N
1. 文件系统遍历(目录树结构)8 V; A: g( W* }/ K
2. 快速排序/归并排序算法 2 y' `/ H* l: g# h- a( K3. 汉诺塔问题 / z8 b4 r* G, C! c+ S9 H4. 二叉树遍历(前序/中序/后序) 6 P, C6 |) m& h# r% D% |5. 生成所有可能的组合(回溯算法)9 _( f. \9 q W4 P& ~; P) \# I# H
2 I' \1 U: A' T3 p, h( u试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒,# @, c7 T$ W }% O
我推理机的核心算法应该是二叉树遍历的变种。 F# O7 U+ y5 I w7 z# L2 W. \% j5 D
另外知识系统的推理机搜索深度(递归深度)并不长,没有超过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: * t L3 t5 _- d$ {+ iKey Idea of Recursion# {( q9 O" k6 V* h, V! T' u6 n
/ ^6 e1 V1 t; N5 p7 vA recursive function solves a problem by: 1 Y3 t$ m y3 f1 M+ g% e / ]6 C1 s5 j8 G- _: q Breaking the problem into smaller instances of the same problem.6 E- r2 R/ w' l# D
+ F' D4 ?5 N, k' |8 g E Solving the smallest instance directly (base case). * h$ `# |+ W! Y* @) t4 t& J- {+ A, a9 r* `7 _ s
Combining the results of smaller instances to solve the larger problem.1 ], E6 S6 d! T
8 o! b2 B* ~4 |- ZComponents of a Recursive Function - O* V; A9 `2 ]+ H {# G6 I u4 X7 y2 u3 R. c; e& S# H6 K$ m: n
Base Case:. X$ h" M- y4 Z
9 i: p$ F S& f
This is the simplest, smallest instance of the problem that can be solved directly without further recursion. 5 O" |8 h. N& o+ S* h9 l. p6 C, q- D) b# y( `$ o! p# F
It acts as the stopping condition to prevent infinite recursion. " p6 t0 y, m& I; j& Z' J/ v: V: v9 a( X Q' M6 t! Q! }# D) G
Example: In calculating the factorial of a number, the base case is factorial(0) = 1. : I; q7 ]" f2 d2 Y) f+ h4 ^) M6 ^/ N- z5 A1 `7 q) s
Recursive Case:! g8 U5 F7 g8 t5 d7 K4 |" _5 Y6 j
2 {' M# {8 k3 a& b6 d( b This is where the function calls itself with a smaller or simpler version of the problem. ; @7 z% @% f6 Y( G 7 @1 U4 A! z8 X8 T Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1).7 D9 l4 f4 ?2 b( F
6 y5 B1 {. U* P( ?: y9 b( WExample: Factorial Calculation 2 f* T7 R- ]- q) Y % A# g# `( }* {3 j$ I" s1 @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:8 K' Y1 A; M( f! L: y# o* [: k( E) `
, d i. }4 F) Y ^( I; n' v$ @0 v6 \
Base case: 0! = 1/ W* z* W+ K& ?6 \9 C# B1 j8 Z- ]
% ]+ N$ X' Q# n$ f Recursive case: n! = n * (n-1)! " g1 E- `) ~# \# Q+ j( d& I3 [4 e/ O" @ A" |: m
Here’s how it looks in code (Python):; V3 L. |9 A" X5 K4 c
python * o# a- v4 Y; L! J9 o% B4 h# [; }
! n& l( Z, t( e: [) Z; j$ Wdef factorial(n): 8 L1 L: S. u0 l4 g: K' H7 P # Base case * X+ l. ]9 o: ~ if n == 0: 6 Q# u. R, p+ \; T9 | return 1. S5 y" J" |( f2 T# d: B [$ m6 m/ V
# Recursive case 8 ]. r: V; E9 `* g3 s- \% W else: * \4 Y0 G: X, A return n * factorial(n - 1) # l8 p) S, {/ r# Y- L & |0 R' v y/ j5 y7 ^* |0 C- d. L# Example usage, d) [1 U9 [0 T4 \8 k
print(factorial(5)) # Output: 1206 Z% b; u) d- {: ]
$ Z+ o. z" ~6 d" q6 b7 g) dHow Recursion Works : V8 ^$ ~% Q5 O5 x% T% |9 I# b! B# G7 d2 F5 o" c6 O. ?
The function keeps calling itself with smaller inputs until it reaches the base case.- j+ _2 s _- _
& J w2 R+ L# ~7 `4 Y" a Once the base case is reached, the function starts returning values back up the call stack.% }1 c1 V! {8 d+ N* t
9 C+ \. g( [0 v: V; p' { These returned values are combined to produce the final result.# \0 ^0 p8 w1 R- f- Z
7 k- e9 t& Q8 Q; E
For factorial(5): 2 E& P; K5 x4 ?4 D/ I # B* T" h. D* k% I$ u. B( ?3 B& u% x$ ?9 |# d0 T% w7 f+ P
factorial(5) = 5 * factorial(4) 3 c4 L; c/ I B ^( V5 H Nfactorial(4) = 4 * factorial(3)+ ~0 D& Z7 k4 D9 ^( Q" a/ S
factorial(3) = 3 * factorial(2)& n1 G( e5 b$ v5 b+ u6 }3 i3 n
factorial(2) = 2 * factorial(1)+ ^+ M( n: K+ o5 b/ u! R0 {/ y
factorial(1) = 1 * factorial(0) ! z9 F: f2 p( Jfactorial(0) = 1 # Base case8 h/ I y/ _3 J
* R- h! w# g" }5 M; R$ H
Then, the results are combined:7 M" ?; E* P4 w" ~
/ o/ S- c* P) ?7 O
7 _+ e: w8 K- E. g% L) c2 I 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). ( v* v3 \6 l! O8 K5 `+ s6 N 4 \0 t3 r$ m' b& Z4 L! h Readability: Recursive code can be more readable and concise compared to iterative solutions.% S8 x4 g8 i d$ ]& \
, n4 p+ m7 x( K% HDisadvantages of Recursion 3 U( T1 X$ R" o U) q9 ^7 e( X3 V1 u0 T3 I/ c" R( B+ d
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.$ @! c9 K9 H) C3 A
2 @/ f+ j0 i/ f6 h- j0 Z
Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization). ) u, Z. e8 t1 [/ w% ^0 j) x B5 j/ s3 U: r R; h* w f
When to Use Recursion' H w i8 c2 ~5 [
" L% R# k. q, W8 { Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort)./ B0 h$ ^! s7 N+ J$ ~8 E4 P
- j4 e5 ]" [7 |4 R3 W3 V% E7 v Problems with a clear base case and recursive case.1 G, a2 f# o! _- t$ ?9 O/ U3 w
S5 P0 y/ o$ c" JExample: Fibonacci Sequence P2 L4 N" Y; g) t7 c' x * `. r( S4 L2 ^% q# [, gThe Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones:6 P7 L2 m8 I5 C* T; F3 T$ c( D
- m9 ]6 v# a/ K Base case: fib(0) = 0, fib(1) = 1 5 @* y4 p8 `; f6 U n5 u/ x/ m m e; ]$ U* l, l2 K. G% }
Recursive case: fib(n) = fib(n-1) + fib(n-2) B. I; k k6 T, J2 V9 {% v
6 ^0 g1 [( n9 o# I1 _+ k2 `
python( g: |8 E5 E8 ]( u# E* }+ f
: k* |: y" R9 s1 k, C; F) E/ T
& K2 _6 \4 f( }& t* i
def fibonacci(n): ( ^6 F& C6 l" O5 g! ?$ Y8 X # Base cases & P6 C( |( h$ w if n == 0:- ?% C5 Q. A3 x/ b
return 0 " ~5 E1 ?5 u& Z' w7 H elif n == 1: * M& Z6 \1 X" |) U return 1 2 W8 s7 O0 C/ ~ # Recursive case 2 \# z! ^) }0 |& H else: " X% U% B6 u) t2 E8 K, i- q# ~ return fibonacci(n - 1) + fibonacci(n - 2) 9 j8 I9 N1 z: u' r# S) {6 m. f2 f d! e# H6 ?, u
# Example usage+ M. G+ c7 L2 M! Y; W* [: \2 |
print(fibonacci(6)) # Output: 8 ! i2 Z. T8 J( k3 A; C0 O0 }3 ^* x+ X6 |
Tail Recursion ! e B. m1 T4 T4 S 3 _& R F) u- `. H" N9 dTail 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).: ?' E" \! F1 H1 L
0 F' y' b6 y; v$ sIn 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 现在的开发流程,让一个老同志复习复习,快忘光了。