$ }1 a9 m* j; j: i: c- J递归是一种通过将问题分解为更小的同类子问题来解决问题的方法。它的核心思想是:**函数直接或间接地调用自身**,直到满足终止条件。 " @- q% n7 v0 I1 T+ e2 D & m. ?( A% L+ X5 q, |1 y1 u 关键要素 & H' r' J4 @4 r* }+ Y1. **基线条件(Base Case)** 2 H* M- C, v( q3 V2 ^& o* J( J - 递归终止的条件,防止无限循环8 W& |0 T. h: w2 U% H% b8 Z; k" T5 F
- 例如:计算阶乘时 n == 0 或 n == 1 时返回 13 i6 G( ?. }" w
. }! w% [/ K0 _8 f) l! ^4 R% `. q. B
2. **递归条件(Recursive Case)**1 c2 c" C8 |$ `8 j1 b
- 将原问题分解为更小的子问题 / D7 ~2 L& n" b- t5 V- [5 k - 例如:n! = n × (n-1)!7 s6 F: v1 F0 h' k& w# ~% ~4 p
' Q- C: N' _2 A- m 经典示例:计算阶乘$ o. I( m: S+ E7 W# I( D
python4 l8 O7 P9 L4 H/ T. [+ p
def factorial(n): " Z8 X6 Q" K6 C3 N if n == 0: # 基线条件2 d4 ^7 C+ i; W3 y1 ]
return 1% L! T6 |+ }$ d% P
else: # 递归条件 / L- y! Q9 U+ o- O& U7 T/ N% K return n * factorial(n-1)$ h W: @ a; i5 v& D( d/ V4 o) l
执行过程(以计算 3! 为例):* I O" h3 ]* d6 }" ~
factorial(3)0 B2 V1 J1 M8 d) e! n, ?
3 * factorial(2)% o2 R$ W c* \9 f1 A% a
3 * (2 * factorial(1)) & Q& P0 a x/ r3 * (2 * (1 * factorial(0))) ; I% u$ |. E# [' l8 C3 * (2 * (1 * 1)) = 62 }5 D! {3 ^6 J7 p4 r2 d1 [. C
2 c! w. i& A6 H( C4 ^
递归思维要点 : ^1 [/ p3 x9 H0 c3 C" i( T6 H8 `1. **信任递归**:假设子问题已经解决,专注当前层逻辑2 _: a7 E9 ]( F1 I/ i
2. **栈结构**:每次调用都会创建新的栈帧(内存空间) ! m1 q7 m, m8 Z3. **递推过程**:不断向下分解问题(递) $ E1 j3 {8 b0 b, f& Q1 H. {4. **回溯过程**:组合子问题结果返回(归)3 \6 Q! E6 M$ |& ]% S- o
5 W. c j$ E, f: U2 Q 注意事项 8 w' U0 X8 \) E# j) \8 h- o0 ~, g必须要有终止条件 + y3 C4 G$ d9 C- Z% `# I" D递归深度过大可能导致栈溢出(Python默认递归深度约1000层)9 W: ^- y& N- [2 N( p& ?5 y
某些问题用递归更直观(如树遍历),但效率可能不如迭代 . _2 G. E$ k' q9 ?" z. G U尾递归优化可以提升效率(但Python不支持) + N* n$ q6 r7 u+ ?" _3 C5 R, |, {. d; w. N0 T
递归 vs 迭代8 S, `! y! o2 K4 L& Q5 r
| | 递归 | 迭代 |( d) ^5 {# L% B1 f. {
|----------|-----------------------------|------------------|8 B5 P5 U2 o& \
| 实现方式 | 函数自调用 | 循环结构 |4 d0 m+ O% ^/ ~* K- Q
| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 | & w8 {+ d# m, h& e9 z| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 | + x7 W$ H5 [* R; p1 x2 r| 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 | % U( n8 Y, j/ i" Y4 F k+ V; w0 E6 ]& @
经典递归应用场景 4 s" j D! Z0 Q1. 文件系统遍历(目录树结构), `3 x: e ^; }7 ?# _
2. 快速排序/归并排序算法 0 s6 _( ~; l! m+ F) B3. 汉诺塔问题& v: c3 o. L! i9 Y+ D) x
4. 二叉树遍历(前序/中序/后序)2 F: B) [+ |* Q0 U6 D( F3 o- [
5. 生成所有可能的组合(回溯算法) - ^9 x* J) n1 J* w9 D# T# r 2 P6 T; S1 t5 l9 T! l- Y, ^试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒,3 B+ m/ w' Z5 y4 [! t
我推理机的核心算法应该是二叉树遍历的变种。 7 y$ }3 o( _( Q6 u另外知识系统的推理机搜索深度(递归深度)并不长,没有超过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:) h1 A$ E$ N3 v
Key Idea of Recursion9 i; P5 f& Z( e) |% ~4 e* z
* L/ L! t+ b$ z
A recursive function solves a problem by: ' O E) K) I l0 y) e# C$ i+ Y- S" k
Breaking the problem into smaller instances of the same problem.( ]6 G9 M0 C; I
0 n# l" x( K( ~) ] Solving the smallest instance directly (base case). 0 o' D9 n3 ?2 F$ `* r; l& N6 l/ l8 `4 J4 X
Combining the results of smaller instances to solve the larger problem.0 o* E0 U/ v! K0 h
' z+ i% C$ ~. F
Components of a Recursive Function 0 ^3 W9 I% N6 e* i# t1 g, N3 f! ?! K, `8 o+ V: n$ |4 g
Base Case:8 h0 Z6 Z5 s1 h: u O* Q; }
2 R% L& K/ S) A, @5 r; J% X
This is the simplest, smallest instance of the problem that can be solved directly without further recursion." i6 ^1 I3 r: W( t
: I6 T, N# c1 n6 }& d; b$ p4 s; G
It acts as the stopping condition to prevent infinite recursion.9 [6 j |! B) f5 O& U1 ~
; w3 D% n. A# b, f Example: In calculating the factorial of a number, the base case is factorial(0) = 1.# @( T! v! J& S
% s& Z7 }& @9 I% c Recursive Case: + h- Y; W; n' |" O2 w3 l2 T" V3 D; N1 X: s) z1 m/ I; m1 d
This is where the function calls itself with a smaller or simpler version of the problem. ; V( O) m- H8 e# C4 b' \7 s4 A$ K8 `1 a! _+ J3 J8 m
Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1). % ]. R$ f7 y" ~7 F$ n) ? v& ?0 Z) X$ E1 K
Example: Factorial Calculation ; J/ z: [+ F; {- @0 |9 m5 G; c! O% Z* t6 ` e5 l
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: " q6 H7 C c8 P& d) B2 ^7 m* V/ T% W l/ N! ~4 c) y) z
Base case: 0! = 1 " e2 h7 ?# J: b$ ]- f) F. b9 R) V
Recursive case: n! = n * (n-1)! ! \" V4 u/ t& R4 F# c4 ~) J ( Y7 K9 u; d2 c, F! ?: [Here’s how it looks in code (Python):3 m5 B$ c& z2 m6 }
python) C3 |0 R8 x/ ]& S
% K X0 e0 V, @7 h ' `0 A$ u9 e# D! kdef factorial(n): ( U' t7 ~! T: B( Y # Base case+ c; s' f1 q8 O0 l- y
if n == 0: $ u3 @! n, B! o6 n$ H return 1: g4 v5 g* e- ~
# Recursive case2 o; s. B( F2 I0 q# k
else: # a r! G* b. u0 x4 h return n * factorial(n - 1) 9 K, N( k# s: n : z" k6 Q. _ j: P3 |$ z# Example usage , }6 X, U9 ]' l- I) Yprint(factorial(5)) # Output: 120 , n$ L W8 v8 }2 y3 l# E; w* ]- v
How Recursion Works# M N; y8 F+ w7 P0 G/ }! `* x
$ e* Y7 [2 y, J; k5 o The function keeps calling itself with smaller inputs until it reaches the base case. " J3 K* E: |0 q2 G( n. z , T( ^. O& J& N- J N4 g Once the base case is reached, the function starts returning values back up the call stack.+ Z: B# H2 g5 p! }: N+ w
1 ~! Q( b' l+ D$ h5 ? p$ `
These returned values are combined to produce the final result., @$ [3 s, ]- o
9 S' a. d- w y& T- WAdvantages of Recursion 4 c& f7 {! V5 x1 M% M0 s }; H# \. B0 {# _
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). " ~& T" x: t1 v) T" r5 y# G9 }0 J6 r) H, d# M- y7 Y! W4 a) N# V: |& K
Readability: Recursive code can be more readable and concise compared to iterative solutions." G& K# c" A# a" G
: I! E' G, Y3 c A2 nDisadvantages of Recursion% U. X* j; `; d% {
" o$ f A( T$ k, u 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. * w$ Q5 e: \6 M; `6 o( f" G& j4 @# w, H" f# }; B" X# K3 g, i
Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization). 7 a ~, o" f+ ^; _! ?+ i/ r+ x) d* W; I+ k5 G, h# r" q
When to Use Recursion 0 ?# F n. F' U + A' Y; Z% @. Z/ ]( d3 P; \ Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort).0 h) @! m3 V4 f. E" d
. [9 S" X% x- b0 ~( b, E0 g4 t( s
Problems with a clear base case and recursive case. 8 S) s9 W' I7 B* ^; R" F. o* @, \* i" }& X
Example: Fibonacci Sequence0 w% p0 M! s L
; p- k1 V/ j0 |* ^The Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones: % z) X6 L' S4 v4 e) u5 ]; g9 `" [* G7 t* S& d* q Q5 ?4 [
Base case: fib(0) = 0, fib(1) = 1 ! c, I z5 T/ i$ [5 ]( N/ x: T4 e1 g6 R$ P: u
Recursive case: fib(n) = fib(n-1) + fib(n-2)$ p! z0 F; g" o( s; K/ [1 H
) ?5 E0 b/ i' [! l! k u4 T2 S( Kpython1 A3 A9 l6 W# L( F' D2 ^
`; o& \, [3 A( e: v & d! R- c( I5 m( hdef fibonacci(n):: n, p( Y6 J+ |
# Base cases . `! H( Y3 h$ L) F& M u' r if n == 0:$ c$ P4 J* e4 ?2 u
return 0 . ~( k% A: a% d2 m1 E" _ elif n == 1: , g! l6 a2 g6 r. b" T$ R return 1 ( m9 r6 C1 p, x" H2 O: Y+ G # Recursive case ! {# o$ f5 ~0 S; w# Y8 I, E5 ^4 M6 W else: % p, l# k7 ^& e: Z5 O return fibonacci(n - 1) + fibonacci(n - 2) 6 P: o2 S! C& a' l3 j, J" k, p& Z- N: o
# Example usage / {7 W0 y/ Z9 S. fprint(fibonacci(6)) # Output: 86 E. p' V9 T: T" G ~- I& q4 M
, V( d2 x6 ^% x" M% {
Tail Recursion ' V) t* I9 k( \3 e3 m' V; x/ \% ^* \; R2 v& J
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).2 q: ~" b3 ]& z+ p g3 z7 @
# b: |9 o% l$ K6 ~% U8 C* t. V0 v0 hIn 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 现在的开发流程,让一个老同志复习复习,快忘光了。