recursion - 递归函数中的堆栈实现

标签 recursion f# stack depth-first-search backtracking

我正在尝试使用深度优先搜索来实现递归回溯功能,但我陷入了需要知道我在矩阵中的先前位置的点。

这个想法是这样的:我有一个矩阵作为二维数组,这是我的函数:

标记当前点,如果该点是我正在寻找的,我将矩阵中的点设置为解决方案的一部分,并将所有先前标记的点设置为解决方案的一部分。
否则我将函数调用到一个有效的相邻点。

问题是第三种情况:如果没有有效的相邻点,那么我需要将该点标记为错误并将函数调用到我之前的位置。为此,我认为我需要一个堆栈来跟踪我以前的 Action ,但我很难弄清楚如何在 f# 中这样做。

let rec  solve (x,y) =

         mark (x,y)

         if (x,y) = pointimlookingfor then
           for x in 0.. array width-1 do
               for y in 0..array height-1 do
                   if Myarray.[x,y]=markedpoint then
                      Myarray.[x,y]<-partofsolution

         else if (List.isEmpty(adjacentslist) then
              Myarray.[x,y]<-wrong point
              solve (the previous visited point)

         else 
              for (adjacentpoint) in adjacentslist do
                   solve(adjacentpoint)

有任何想法吗?

最佳答案

在大多数函数式语言中,默认列表类型是不可变的链表,由于它的构造,您可以将其用作简单的堆栈。
cons被压入堆栈,head从堆栈中弹出。
有了它,我们可以编写一个简单的堆栈模块。

module Stack =
    let empty = []
    let push item stack = item::stack
    let pop = function
    | [] -> failwith "No items in stack"
    | x::xs -> xs
    let peek stack = stack |> List.tryHead

所以,
Stack.empty |> Stack.push 1 |> Stack.push 2 |> Stack.pop |> Stack.pop = Stack.empty //true

在实际实践中,最简单的方法是在递归/折叠时随身携带的某个累加器上使用模式匹配,而不是显式使用上述函数。

例如,让我们为堆栈重新创建一个经典用例 - balancing parenthesis .
每次遇到左大括号时,就压入堆栈,遇到右大括号时,从堆栈中弹出,看看它是否与您压入的最后一个匹配。如果不匹配,则不平衡。
let rec isBalanced stack = function
| '(' | '{' | '[' as opened -> opened::stack //push into stack
| ')' | '}' | ']' as closed -> 
    match stack with
    | opened::rest as all -> //pop from stack
        match opened, closed with
        | '(', ')' 
        | '{', '}' 
        | '[', ']' -> rest
        | _ -> failwith "Mismatched braces"
    | [] -> failwith "Closing before open"
| _ -> stack

"abc() { [ 1; 2; 3] }" |> Seq.fold (isBalanced) [] 

有更简洁的方法来编写它,但这说明了如何模拟具有不可变结构的经典堆栈。

在您的情况下,您可以将 (x,y) 元组插入堆栈,并通过解构它让算法回溯:(x,y)::tail .

关于recursion - 递归函数中的堆栈实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61734644/

相关文章:

f# - IObservable.Add 与 IObservable.Subscribe

c++ - 为什么我使用 std::vector 创建堆栈的程序会崩溃?

stack - *** 检测到堆栈粉碎 *** : a. 终止

java - 使用递归迭代数组列表

ruby-on-rails - 在 Ruby 中迭代深度嵌套的哈希级别

f# - 从代码引用中调用基类方法

当初始化程序具有依赖性时,F# XUnit 测试死锁

c - 使用堆栈平衡括号

javascript - 如何递归地从数组中删除连续的重复元素? (javascript)

javascript - 改进当前的递归函数?