5 D4 g9 c( u$ d5 `5 {$ {* P) u解释的不错 ) ^: Z: b. C+ c' I) S c% n/ r: e+ b/ X
递归是一种通过将问题分解为更小的同类子问题来解决问题的方法。它的核心思想是:**函数直接或间接地调用自身**,直到满足终止条件。0 p, S' x6 d. l( N" v {
& P/ w7 D8 Z3 W% g! u4 a 关键要素6 e% d' ?' |* ^' M
1. **基线条件(Base Case)**8 f3 x- q( }8 | f2 K. e" L
- 递归终止的条件,防止无限循环 ; Z7 h+ R4 W; w; Z$ z p: r% n - 例如:计算阶乘时 n == 0 或 n == 1 时返回 1 6 W/ x2 Y$ q* g% A+ n; i7 b9 r j6 M+ d
2. **递归条件(Recursive Case)** . {8 D( ~1 h; ~ - 将原问题分解为更小的子问题, v' d+ I" K1 _5 D! L) C; ]* K+ L
- 例如:n! = n × (n-1)! 6 P& t# |0 u" `% _# M$ y: W$ a6 R$ `; N' g. J6 {/ v: \
经典示例:计算阶乘 7 t% q- f& s: t& q5 v% xpython , [3 V0 ]2 B3 P# d# q) \def factorial(n): ( D I9 |0 p l5 ?' f2 l7 f# y if n == 0: # 基线条件 # I( b) Q0 K) f2 s6 u* E7 w% u return 1" j8 ?/ z" @* Y$ C1 l4 Y, n6 d
else: # 递归条件 n+ y# ~1 u) f9 w) W
return n * factorial(n-1)/ w. y5 @: g, g9 I1 f
执行过程(以计算 3! 为例): C& v. m% t0 V( d- a/ z% E
factorial(3) $ A- }" U( w! | y4 T& `# x2 [3 * factorial(2) ' h1 ~' t8 J7 ^7 j3 * (2 * factorial(1)) ( k1 z+ `% V6 F, x% v) e4 m3 * (2 * (1 * factorial(0))) / y4 b0 L% w/ d9 b3 * (2 * (1 * 1)) = 6 - U" f" _) i( {0 }& s, Z2 ]- }, j 8 n5 O: k1 j0 Y" j+ [. A 递归思维要点( `9 x3 p8 `5 h% B# n
1. **信任递归**:假设子问题已经解决,专注当前层逻辑" i$ O0 y1 p) B8 u9 L
2. **栈结构**:每次调用都会创建新的栈帧(内存空间) & f+ P/ Q4 y8 `3. **递推过程**:不断向下分解问题(递) " m( Q7 s4 r, t& h4. **回溯过程**:组合子问题结果返回(归) ; R+ F2 f8 X$ o2 J: t / s# b& A: T& w/ W8 i 注意事项* u: a3 w6 J+ q: `" Z8 J# m! O
必须要有终止条件6 H7 `3 \* z+ m
递归深度过大可能导致栈溢出(Python默认递归深度约1000层) : t5 R: l* G2 I. ?) b( K3 l! V5 {1 r某些问题用递归更直观(如树遍历),但效率可能不如迭代 T4 h3 C. |' i: |2 r& g
尾递归优化可以提升效率(但Python不支持); _: s( S! d( R/ a; w h( Y& u
. b7 R% D7 t! E3 y/ X5 `! b2 U
递归 vs 迭代 % j j: Z& R: I+ V j$ b| | 递归 | 迭代 | , t" l" j8 g) p' T* c* \|----------|-----------------------------|------------------| 0 Y% B) Q* [ D! ?/ b& X| 实现方式 | 函数自调用 | 循环结构 |! a, u+ |$ d! I4 l1 u1 m( i1 c# `
| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 | 1 j3 W' z' `, F$ c( A" V S& T3 F$ r| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 |: a3 X# G% c, n y6 _( `1 {6 V7 J
| 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 |8 c+ m) [+ O+ ?6 b" C+ D
3 U7 s$ _: f& D/ c0 K9 ] 经典递归应用场景 9 p5 e$ h H" ]. h1 u1. 文件系统遍历(目录树结构)* `: e; k* ]$ y/ J& s
2. 快速排序/归并排序算法 % Z- e: K+ T& M3. 汉诺塔问题) n/ U2 r# D' u- k+ M; U! m7 S5 E
4. 二叉树遍历(前序/中序/后序), |5 k2 r/ [3 q1 H
5. 生成所有可能的组合(回溯算法) Q/ s3 `: ]. |& p* x7 v! p4 U1 M ! z6 j7 Y" ?' i& b. p! }2 V. @% L# K试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒,3 s9 G' t. I1 H* j/ `8 P$ Q7 q
我推理机的核心算法应该是二叉树遍历的变种。 8 ~. z( N+ q! N; 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 J$ Q! M/ UKey Idea of Recursion& A* H$ _& R+ q" _
( H9 Y! M e. Q- s$ q! N' l6 D
A recursive function solves a problem by:( |$ c& n( ?2 ?- b
1 H) {* _) E. R# E" N, a Breaking the problem into smaller instances of the same problem.5 _: o& x6 G6 q, K6 {# p8 b! ~
1 W+ U9 \+ k4 t2 P
Solving the smallest instance directly (base case). * e0 z" I/ h) W: n9 U3 R9 Q$ ~" J7 ^6 \8 ]; s) e _
Combining the results of smaller instances to solve the larger problem. 1 Q9 a% |' F6 q/ B. w ) S- s. f; G2 c: L* G: ?Components of a Recursive Function : n; G3 K; \# U% x - H" G# |- x* z Base Case: W# k0 X& `6 W' x4 |
, d0 x- Q1 _" U8 L! Y! | This is the simplest, smallest instance of the problem that can be solved directly without further recursion.3 K5 A( B8 L- i* Z" s m9 ^
0 W" j1 M* X* ^+ ^$ d! y It acts as the stopping condition to prevent infinite recursion. 3 [+ ~) a8 P8 E 6 V) d* J; ?: @ Example: In calculating the factorial of a number, the base case is factorial(0) = 1.6 X+ k/ u: l/ l9 I4 z3 G- b
% E$ Z! s4 J0 u, u! `' P
Recursive Case:/ N5 u% R) H( N/ o6 l
6 D2 r: j! p& b/ R" {) o& n8 I This is where the function calls itself with a smaller or simpler version of the problem. J$ b3 V: G% R" j1 M# J# C$ q/ {/ x. ^$ w6 T7 u% P" e
Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1). $ r+ _# H" K5 W+ m2 d9 ^4 l* {2 R 8 t# V7 ?* O7 p0 \Example: Factorial Calculation 0 z# T7 {5 w; d5 e( Q8 _! b) R( ]# j$ z8 |/ }* \
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:5 y; [2 n0 p, ^2 e# D2 Q) M
7 N1 _' K5 Y) M9 ~ k Base case: 0! = 10 [$ e% ~, ~5 O0 b: Q) ~9 d
4 w0 N9 A8 c' ]* y) e
Recursive case: n! = n * (n-1)!% i8 f2 q2 o# M" k8 } ~% c0 ~
' j* E& P+ V, ~
Here’s how it looks in code (Python):7 f$ B) g$ }. `0 ?" D
python/ f1 E0 j2 k; C$ |4 }& q
1 p0 P' a4 q Y/ S
/ f3 w. M1 R* A' H! a# c4 k9 h
def factorial(n):. e! z- t( j* h% C; o
# Base case# w) a" G, w" h& L: Z: ~5 g
if n == 0:% V/ q# F( `) T! a
return 1% S, V3 f- B3 d7 Z
# Recursive case " c! y; P6 |4 t2 d0 [; p& e else:6 b) h* d! G4 O4 u b. A
return n * factorial(n - 1)4 A9 @5 o1 c9 n; @4 W9 s: o' V# Q' y$ |
) l; Z" b: b) V2 K3 r" r$ F& {; i& r! F
# Example usage 7 ^3 M1 A4 }( H6 x& }4 E9 Oprint(factorial(5)) # Output: 120 ; q) A! |$ ]7 @2 e6 l9 `: B, x, t" ?7 O N+ ^! J3 n/ k
How Recursion Works , [) C' C [+ d E , D8 \& A# Q3 k+ [$ d- q/ {# J The function keeps calling itself with smaller inputs until it reaches the base case. : W3 _+ _/ @9 z$ I: |. {/ k* A2 V1 b* ] Y
Once the base case is reached, the function starts returning values back up the call stack. 9 U6 R" S/ C1 G. A8 G( z6 J3 C7 |8 ^! z
These returned values are combined to produce the final result.3 a- B) p' d! z6 `% c
$ h1 r7 l# D" O. y3 v5 m
For factorial(5): - T5 |. K3 @. t, Y8 w; o5 b3 n2 `. \" F' [4 A
- F T! D4 |% U) s q+ J* j* \9 k
factorial(5) = 5 * factorial(4) 5 @. A" w& n: j7 ]4 i& ?4 Pfactorial(4) = 4 * factorial(3) 1 Z9 X1 A* m9 `! p4 O Efactorial(3) = 3 * factorial(2)# M* @* R* e# A8 a; H$ c& q
factorial(2) = 2 * factorial(1) 9 a- D: c: p- u. d* e2 d8 H; K3 kfactorial(1) = 1 * factorial(0), H0 d: E' I& c$ m1 J' ]
factorial(0) = 1 # Base case k1 N; |6 @$ [3 C* j' \ & z# i* Y1 @, W' z7 C# Z& o2 uThen, the results are combined: & P. J8 y1 P5 e3 V! g/ t( t$ L" A6 g# K! A# i/ D* I
$ R6 F: x5 U8 {& r
factorial(1) = 1 * 1 = 1, y8 |$ _7 ? ]. S- v
factorial(2) = 2 * 1 = 2 , h6 s& `! {* P5 I% rfactorial(3) = 3 * 2 = 6) b) Y7 l8 [4 R/ K( U
factorial(4) = 4 * 6 = 248 D7 \* W J9 G7 x' f: G5 `
factorial(5) = 5 * 24 = 120! |% T- h: J% H" t8 U5 c2 i
[ F& ]! ~/ s4 w: K" {+ N
Advantages of Recursion 6 }: Y- y5 o4 y8 x7 ~ & S* n% B% m* K- U/ E. G 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). " j& q# k6 `9 f: | 0 N2 U4 w( G" p# G! E/ H9 a Readability: Recursive code can be more readable and concise compared to iterative solutions. & h% ?4 _! }: y; @$ U$ m. @1 z2 d$ K4 R6 p1 {( O
Disadvantages of Recursion 8 J1 R; I4 t F+ L 5 R, `' [3 `4 ^ 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. 2 y" P1 f7 ?7 l9 S3 X+ ]; a! v . p, U7 _. ^2 t Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization). 2 |; N1 C; t4 v/ G' Q+ Q 1 m" W9 [4 R% u% Q% @0 T- P( g* g5 bWhen to Use Recursion1 d+ H |9 T; \ ~6 ~
. V# b/ d/ W1 L
Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort)." v l/ V( ?# I( D- ]6 v
6 c4 e- a8 \4 o# v$ j; B$ m
Problems with a clear base case and recursive case. - F- j9 \- j2 C$ Q9 m8 @6 K& d! e) r; C; U4 F
Example: Fibonacci Sequence( M; s* y3 i- N4 B, U2 S
0 H7 \& Y" `. u4 X* kThe Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones: 5 G+ A, b6 ?/ |/ Z9 Z5 ? . E9 _3 @. |' `: L l Base case: fib(0) = 0, fib(1) = 1* k8 R" F9 A! @$ B! x# O
% x8 L/ ~( @) h" A9 G
Recursive case: fib(n) = fib(n-1) + fib(n-2) ( W- ~! D6 ^. t0 S1 u& m0 ?( Z! ~1 N/ a0 Q
python- v" W _: m) e! _% b" ?
* m5 x8 h$ N5 F2 U) s( g 8 ^5 s; Z+ Q0 V1 e4 l' _def fibonacci(n):. ^' f: ^$ @& b% ?3 L- d
# Base cases - A6 \ b/ C- X( k if n == 0:& H* U9 V G1 [7 I, Z- d
return 0 - w5 e8 h, q7 N3 C \8 k5 ~5 k elif n == 1:- ~5 ^* R$ m, X, R, w8 B/ H \: ]8 P
return 1: |: j8 O/ \, q z6 {" u
# Recursive case 6 x/ u% k" x- Q/ O else: 7 c$ ~1 H1 U( P& R$ Q0 y return fibonacci(n - 1) + fibonacci(n - 2) " Y; {+ {+ K( W, ^# [3 N! l/ w) ~6 \% J4 o9 J. e
# Example usage 2 G. H" z* ]" j/ d8 Vprint(fibonacci(6)) # Output: 8; L+ W; y8 E) ]8 S$ Z1 E7 K
( k- L$ W0 g" h* K
Tail Recursion" ^/ V1 F4 j, b: C6 g, H" U- l) o
& E! S) v( Y+ QTail 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).$ ^9 P/ Q! D! x |
& C5 N% P" I2 I0 o, IIn 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 现在的开发流程,让一个老同志复习复习,快忘光了。