`2 {; k! r0 n S 经典示例:计算阶乘 ; [5 o4 l( a$ R" Spython + S5 m3 V( ]; [* I; Ddef factorial(n):8 h4 R% S4 w3 b1 i4 r
if n == 0: # 基线条件& `' W+ ~6 j9 o) {0 Y5 K
return 12 p2 p: q- T; r9 ?2 F
else: # 递归条件 ! C* {6 Q6 U# E( ~9 c# K return n * factorial(n-1). Z0 f$ u& L; c( q4 m
执行过程(以计算 3! 为例): $ n0 ~' }( B* @factorial(3)' r! Z( t2 V; O7 u) B
3 * factorial(2)- n+ H% K( U. P( F7 m
3 * (2 * factorial(1)) $ }2 O3 _& w6 O3 E9 H, Z3 E8 H3 * (2 * (1 * factorial(0)))3 ~1 } {0 o8 b, p/ K+ ~" p
3 * (2 * (1 * 1)) = 6 8 u/ G1 ?" e: o! z8 \/ @0 t* A3 W" g5 a4 c 2 _+ T4 G6 S. {8 A O6 Q% J. q 递归思维要点 . G; f0 r. v3 ?; G5 w6 g1. **信任递归**:假设子问题已经解决,专注当前层逻辑( m1 A1 ^; S& t5 Y, }5 R" W
2. **栈结构**:每次调用都会创建新的栈帧(内存空间) ; }4 |5 f6 W( E ^" X6 x8 Q3. **递推过程**:不断向下分解问题(递) 5 t* D8 v* U3 ]4. **回溯过程**:组合子问题结果返回(归)1 ^, F; w& N* m; `3 Q0 Q
! \: e4 h0 T7 P6 J7 w9 t, G5 k, M
注意事项 " o* G; D, t* \/ u# @$ g必须要有终止条件! M5 i) T# n& j8 l
递归深度过大可能导致栈溢出(Python默认递归深度约1000层) 3 z9 A8 C& x% d2 [某些问题用递归更直观(如树遍历),但效率可能不如迭代$ f& h4 ?5 {3 B2 C: z, x9 g" x* s
尾递归优化可以提升效率(但Python不支持)8 M3 B( o( |3 L& w
! F7 p# Y4 |1 V+ `4 k4 V4 n 递归 vs 迭代# R9 r. Z1 @! L* Z
| | 递归 | 迭代 | : p2 v6 _( \. v* q5 p6 K|----------|-----------------------------|------------------|: B/ v1 ^8 h ~. e) H6 s' s
| 实现方式 | 函数自调用 | 循环结构 | 9 Q2 m; M( K: B; K: p| 内存消耗 | 需要维护调用栈(可能溢出) | 通常更节省内存 |5 A, M5 C- @" S6 l/ u
| 代码可读性 | 对符合递归思维的问题更直观 | 线性流程更直接 | " }2 K5 z( i8 m# M3 P' L7 || 适用场景 | 树结构、分治算法、回溯问题等 | 简单重复操作 |% N5 Y* O) R5 f; l# y. Z- |
+ A6 n& }. x$ Z% A+ o- g, f/ X
经典递归应用场景& ?5 t% j/ R0 [! S
1. 文件系统遍历(目录树结构) c R' O7 v4 X- F; k5 d: W2. 快速排序/归并排序算法 3 ~6 c6 H* R# H w% k4 d* r/ s3. 汉诺塔问题) z: a+ [4 u5 b! V9 o: K
4. 二叉树遍历(前序/中序/后序) ( R) ?/ P8 e- [9 `+ Q$ t# a, F! x* E# P5. 生成所有可能的组合(回溯算法) 6 q' ~) U) h! d; [& S5 M% G2 v+ R' j- |6 L" R* v- G3 R% d
试着用递归思维想象:你站在一面镜子前,镜子里有无数个逐渐变小的你在照镜子,这就是递归的直观体现。但记住每个"分身"最终都要有结束的时刻,这就是基线条件的重要性。作者: testjhy 时间: 2025-1-30 00:07
挺好,递归思维要点与我能够回忆起来我当时写递归程序的思路很一致,,或者被它唤醒, - ~6 Q% C: |# b, m) i2 m我推理机的核心算法应该是二叉树遍历的变种。+ J; B% J5 M$ U# M, s# S, @2 n
另外知识系统的推理机搜索深度(递归深度)并不长,没有超过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:& O2 L% g1 p- |
Key Idea of Recursion % W/ M+ E' g! C7 i m L3 H l: p8 i+ v1 c) g8 J* BA recursive function solves a problem by:, B; y) y* m) v; V8 A
) f2 C' Z1 @8 T5 O- r' I Breaking the problem into smaller instances of the same problem. 1 P7 H3 j+ P. f& m4 Q, a) T+ L. u6 j8 O+ z5 a- t
Solving the smallest instance directly (base case). 6 r: f& h% q! D9 z0 _. a& G 1 d; ~0 C+ Z8 Z+ p+ ? Combining the results of smaller instances to solve the larger problem. ' }- X- D5 S9 q& S& O. U% ?5 w ( i+ J) S" ?' m+ s& A/ \Components of a Recursive Function/ F, E7 f+ @' N( I& A
) C, T$ c+ Q5 n$ z' J Base Case: , s% ?: b/ c* @ / c; B- g' W; K9 l1 O$ A This is the simplest, smallest instance of the problem that can be solved directly without further recursion. 0 U& J1 a0 W4 a8 S0 x( i* P * J, B' d# O) Q It acts as the stopping condition to prevent infinite recursion. 5 V# `8 s o4 f+ X! X 0 Z+ `( f+ u* n! w* h1 A5 j Example: In calculating the factorial of a number, the base case is factorial(0) = 1. 5 ]4 A* X: X5 Y' q$ k 3 Z9 N6 v2 j( I" B! ~/ j7 I8 F$ G Recursive Case:1 ]3 k V$ M) @! O- u) F; r, \
7 T8 h, b$ D" Z5 J' P# G p5 C. B
This is where the function calls itself with a smaller or simpler version of the problem., M0 m* C. D7 t! q0 `5 _
- B7 B7 o; `# T% p5 A Example: For factorial, the recursive case is factorial(n) = n * factorial(n-1). ; z6 D5 w- q6 Y S$ V# k8 @) @# H6 F/ B1 z& P) n- R
Example: Factorial Calculation * }$ m7 ]3 }; X; d- K# ]) V! I9 W* r# b/ l/ B4 \. v- t
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: . \: `+ [2 |! n% o0 }4 e! B1 m! Y0 E
Base case: 0! = 1 O9 u5 a# h7 p' u8 ?) L3 L0 v- w) D" Z: y$ _$ [, k
Recursive case: n! = n * (n-1)! $ s+ |' l5 C# G) G5 G0 Y8 Z& N+ T' o7 j& x3 V G$ z
Here’s how it looks in code (Python):" x; Y* A; P& N( P/ I1 D
python ! X# z) L g, {) x+ p0 m( n0 n& ]* o! J% k2 G& N2 _ X
; a. K4 f8 Z5 L0 F8 Q+ s- G
def factorial(n):. u5 i" T& {$ p0 X
# Base case $ Z: N0 H# E' p% k$ l; W if n == 0: 4 x7 S. e+ V1 E9 t return 1+ i6 j9 w+ g& h1 K$ }/ C
# Recursive case : A8 a5 l/ o G else: * A* H' v5 l2 a4 D* P" ?8 p return n * factorial(n - 1)) W& _0 `) p$ E/ J
^% c- g7 d$ }. ]5 T% o# Example usage 3 v5 G, x0 |6 z& J9 j' N; Zprint(factorial(5)) # Output: 120 % I l! ?% k' E& t6 W3 o1 v9 C . v3 M% u: { A8 j8 d( NHow Recursion Works 8 H9 z: o/ \5 o) o3 d$ Q" c. C" l4 U0 Y) v. c
The function keeps calling itself with smaller inputs until it reaches the base case.2 A D, ?6 M# D6 l
! G# [" H1 I5 \$ O+ H4 X$ T Once the base case is reached, the function starts returning values back up the call stack. : N8 t$ u1 N& f I ^ 9 d# E* w# p/ J+ d4 c These returned values are combined to produce the final result., K5 p+ G6 K/ l' M$ q# y1 E
" v$ O) f# |. U; W6 H
For factorial(5): ; H0 z. L L/ D- g! Z' A% y: J$ N& y* J5 M; s3 Y0 k1 V) O
* Q. I7 I* M* L$ ?. f! ?" @Then, the results are combined: 2 `$ b% U( y( b% B& C & I2 V/ k# m7 F, {3 U- C) `- G 2 |9 g- `/ q5 Mfactorial(1) = 1 * 1 = 13 X- ~( }1 \( k
factorial(2) = 2 * 1 = 2 2 N( w- H4 F; D! kfactorial(3) = 3 * 2 = 6 C/ e7 |- l% I% `6 ]
factorial(4) = 4 * 6 = 24 : M6 t* k7 i7 g2 Xfactorial(5) = 5 * 24 = 120 & O$ ~3 l5 F0 m5 R: I/ a9 f# F, Q6 s$ _
Advantages of Recursion ) K N$ ?, l7 y* b- l 3 y0 l6 {4 ]4 Y( a- R 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).5 h7 N _5 I8 R% F4 ?
( F# d# _( Y6 d# c Readability: Recursive code can be more readable and concise compared to iterative solutions.! Z5 B5 a, m: @9 ^2 J
6 G) C& X3 R( i+ rDisadvantages of Recursion. o# k- T8 Z" f' J( |* F$ F( p; V
8 h3 x: Y/ {0 O- ]' 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.. z/ S+ z, c Y
1 @( ^4 U# }. M6 ]
Inefficiency: Some problems can be solved more efficiently using iteration (e.g., Fibonacci sequence without memoization).9 Q; }: y1 _" U7 u
: _- {4 U& ]6 r# Z+ C
When to Use Recursion 3 v) H9 `* M. U; @& Q9 H. r, A/ ~9 {% s6 _$ @7 } o
Problems that can be broken down into smaller, similar subproblems (e.g., tree traversals, sorting algorithms like quicksort and mergesort).! D3 x: |- K) ~: ]: H; v7 c
% g) X0 f# z8 L6 c6 K Problems with a clear base case and recursive case. + `! c. _$ F. H- l6 } 4 \1 `" J% L0 Z# ^! UExample: Fibonacci Sequence % o5 y# R4 P. d- M) c7 m& r: A$ y0 z# S, X$ t
The Fibonacci sequence is another classic example of recursion. Each number is the sum of the two preceding ones: . c1 O: s/ T( ~ 8 _2 l5 x& X- u6 N" n Base case: fib(0) = 0, fib(1) = 12 @. @0 @. j9 c, ~" g7 `$ B1 S0 F
& B9 x/ V- c- L* h* wpython ' x Z. G1 a m& p: w: u% F! B/ t. g2 e3 P% r, F- w# `0 r
% x8 A; D% Q0 i7 L
def fibonacci(n):% l# |7 O) r0 v2 @5 l" |5 Z5 x
# Base cases0 T8 z! h- D7 n; P6 X8 X
if n == 0:2 L7 q8 r3 O7 Q% v/ I
return 0 3 [9 c1 n. ]& m% K elif n == 1:) w0 `3 f8 O5 F/ d6 ?% g" S
return 17 W3 B S/ v; U4 k8 V/ l! ]+ [
# Recursive case * }) T- ^4 k# h T0 l | else:, a' e2 J9 w$ L; H! ]5 f: w
return fibonacci(n - 1) + fibonacci(n - 2)' K u5 Z4 u1 g; ^' ^# t, b
% k& }/ Q/ p( _
# Example usage9 [$ g; a* \# R8 ^+ \
print(fibonacci(6)) # Output: 8 , ^$ A D6 j, ]0 d; K( s: ?& S0 i4 Y1 n
Tail Recursion. q4 s/ s: Q. q+ D
7 s/ E1 s$ @" O4 G' o, i# _
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).! L' B& I' F8 n W O
- [+ R! J/ T1 N4 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 现在的开发流程,让一个老同志复习复习,快忘光了。