汉诺塔问题递归与非递归算法
汉诺塔问题描述如下:
有 A、B、C 3 根针,n 个圆盘(从 1..n )从上到下,按小到大顺序放在 A 处,要求每次移动一个,并保持从小到大的叠放顺序, 利用 C,把 n 个盘子移动到 B 处。
递归算法
递归算法比较容易理解
fn hanoi(n): hanoi_move(n, 'A', 'B', 'C') fn hanoi_move(n, from, to, medium): if n <= 0: return hanoi_move(n-1, 'A', 'C', 'B') println("move {} from {} to {}", n, from, to); hanoi_move(n-1, 'C', 'B', 'A')
非递归算法
重新思考整个移动过程,在处理 n 从 A 到 B 时,需要先处理其上的 n-1 个圆盘从 A 到 C,直到 A 处只剩下 1 个编号为 n 的圆盘,这个步骤定义为 Step :
struct Step { n, r, from, to, medium }
r 表示当前编号为 n 其上面还放着有多少个圆盘,当 r
为 1 时,就可以移动编号为 n 的圆盘了,即:
Step(n, r, from, to, medium) 分解为 1. Step(r-1, r-1, from, medium, to) 2. Step(n, 1, from, to, medium) 3. Step(r-1, r-1, medium, to, from)
可利用栈或双向队列保存中间状态,一直到分解完成,注意,用栈保存时方向与分解方向相反:
fn hanoi_move_stack(n, from, to, medium): if n <=0: return s = Stack() s.push(Step(n, n, from, to, medium)): while !s.is_empty(): step = s.pop() if step.r == 1: println("move {} from {} to {}", step.n, step.from, step.to) else: s.push(Step(step.r-1, step.r-1, step.medium, step.to, step.from)) s.push(Step(step.n, 1, step.from, step.to, step.medium)) s.push(Step(step.r-1, step.r-1, step.from, step.medium, step.to))