You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lavos/cap3/ex5.go

70 lines
2.2 KiB

package cap3
import "lavos/common"
// Ex5 例题5 汉诺塔问题,输出移动的步骤,可指定算法类型,每做出一步移动操作都将会调用callback
func Ex5(beadNum int, algoType AlgoType, callback func(from string, to string)) {
switch algoType {
case AlgoTypeRecursion:
Ex5Recursive(beadNum, "A", "B", "C", callback)
default:
Ex5NonRecursive(beadNum, "A", "B", "C", callback)
}
}
func Ex5Recursive(beadNum int, a, b, c string, callback func(from string, to string)) {
if beadNum == 1 {
// 如果只有一颗珠子,直接从 A 移动到 C,结束
callback(a, c)
} else {
// 第二步:将所有在 N 之上的珠子(即 N-1 颗珠子)从 A 移动到 B。此时 C 是中转站
Ex5Recursive(beadNum-1, a, c, b, callback)
// 第二步:将 A 的珠子移动到 C
callback(a, c)
// 第三步:将剩余的 N-1 颗珠子从 B 移动到 C。此时 A 是中转站
Ex5Recursive(beadNum-1, b, a, c, callback)
}
}
type _step struct {
n int
from, transit, to string
}
func Ex5NonRecursive(beadNum int, a, b, c string, callback func(from string, to string)) {
stack := common.NewStack[_step](beadNum * 5)
// 最终状态:a->c,b作为中转
stack.Push(&_step{
n: beadNum,
from: a, transit: b, to: c,
})
for !stack.Empty() {
status := stack.Pop()
if status.n == 1 {
callback(status.from, status.to)
} else {
// 把子问题的三个基本步骤压入栈
stack.Push(&_step{
n: status.n - 1,
from: status.transit,
transit: status.from,
to: status.to,
})
stack.Push(&_step{
n: 1,
from: status.from,
transit: status.transit,
to: status.to,
})
stack.Push(&_step{
n: status.n - 1,
from: status.from,
transit: status.to,
to: status.transit,
})
}
}
}