你会如何重写这个递归函数来删除递归?

时间:2009-12-29 19:00:54

标签: vb.net recursion

我得到了那个小功能(我更改了变量的名称)

Private Function everythingLinked(ByRef myClass As cls, ByVal found As Boolean) As Boolean
    If Not found AndAlso myClass.checked = False Then
        myClass.checked = True
        For i = 0 To myClass.numLink 
            If Not found Then
                found = everythingLinked(masterArrayOfCls(myClass.linkNum(i)), myClass.isMiddlePoint)
            End If
        Next
    End If

    Return found
End Function

我想重写它,所以它只是循环而不是递归而且我现在迷路了,任何人都可以给我一些方向或任何东西?

编辑它的作用。 (英语不是我的母语抱歉)

我正在将一个类传递给此函数(找到的起始值为false)以确定它是否链接到树的中间。

该类有一个最多4个链接到其他类的数组,它可以是循环的(这就是为什么我有一个checked_link布尔值)。

它执行递归,直到没有更多链接(返回false)来检查或直到找到中间链接(返回true)。

修改

例如,这个

  pos 0中的

与1的链接   在pos 0与6的链接   在pos 1与0的链接   在pos 1与7的链接   在pos 2中得到了与3的链接   在pos 2中得到了与8的链接   在pos 3与4
有联系   在pos 3与2的链接   在pos 4与3
有联系   在pos 5与11的链接   在pos 6与0的链接   在pos 7与8
有联系   在pos 7与1的链接   在pos 8与9的链接   在pos 8与2的链接   在pos 8与7的链接   在pos 8与14的链接   在pos 9中获得与8
的链接   在pos 10与11的链接   在pos 10与16的链接   在pos 11与5
的链接   在pos 11与10的链接   在pos 11与17的链接   在pos 12与13的链接   在pos 13与12的链接   在pos 13与19
有联系   在pos 14与15
有联系   在pos 14与8
有联系   在pos 14与20的链接   在pos 15与14的链接   在pos 16与10的链接   在pos 16与22的链接   在pos 17与11
有联系   在pos 18与19的链接   在pos 18与24
有联系   在pos 19与20的链接   在pos 19与13的链接   在pos 19与18的链接   在pos 19与25的链接   在pos 20与21的链接   在pos 20与14的链接   在pos 20与19的链接   在pos 20与26的链接   在pos 21与20的链接   在pos 22与23的链接   在pos 22与16的链接   在pos 22与28的链接   在pos 23与22
有联系   在pos 23与29
有联系   在pos 24与18的链接   在pos 25与19的链接   在pos 26与27的链接   在pos 26与20的链接   在pos 27与28的链接   在pos 27与26的链接   在pos 28与22
有联系   在pos 28与27的链接   在pos 29获得了与23的链接

中点将是pos 15

上面的代码可以证明每个位置都可以与中间点链接

所以初始arg将是

  everythingLinked(random pos, false)

在这种情况下,它将永远是真的

5 个答案:

答案 0 :(得分:3)

我可能会遇到这种情况,但以下内容应该会删除递归。基本上你需要跟踪当前的myClass实例,然后转到下一个。

found = false
current = firstObj
While Not Found
  For i = 0 To myClass.numLink  
    If myClass.checked_link(i) = False Then 
      myClass.checked_link(i) = True 
      found = myClass.isMiddlePoint
    Else
      // looked through all items and need to break?
      Exit While
    End If 
  Next 

  current = masterArrayOfCls(myClass.linkNum(i))
WEnd

你需要在那里添加一个条件,以确保你不会永远循环,也许是一个“if myClass.checked_link(i)= False”的其他条件,表明你搜索了整个集合,需要摆脱循环。

答案 1 :(得分:1)

在一般意义上,通过自己实现堆栈,可以用非递归例程替换递归例程。

通常会进行递归调用,将通常传递给递归函数的参数推送到堆栈中。然后继续循环。当您触及递归的底部时,弹出所需的数据并继续下一个路径。当堆栈为空时,您就完成了。

答案 2 :(得分:1)

在我看来,您有一个图表,并且您正在执行深度优先搜索,以查找从特定节点到作为中间点的节点的路径。

如果我理解正确,你不需要为每个链接都有一个checked_link属性,你只需要为你设置的每个节点(你称之为类)提供checked属性你开始处理那个节点。

要删除递归,您需要一个辅助数据结构。如果要保留当前使用的算法,则需要将其作为堆栈(但您可以使用队列使其成为广度优先搜索)。首先将初始类推入堆栈并将其标记为已选中。然后,只要堆栈非空,就循环,从中弹出顶级类并推送所有未检查的链接类,并标记每个类。如果在某个时刻弹出的类是中间点,则终止循环,否则堆栈清空将发出没有找到中间点的信号。

(很抱歉没有提供代码,我对该语言不太熟悉。)

答案 3 :(得分:0)

在这里查看这个问题的细节可能会有所帮助。

您说最多有4个链接,您需要做的第一件事就是确定树的中间位置。因此,如果有< 2个链接比没有“中间”。因此,您只关心传入的类中是否有3个或4个链接。

这将是这样的:

if(numLinks >=3){
look at array[2] and/or array[3]
if(isFound == true){
// do something with it

答案 4 :(得分:0)

感谢大家,这就是我所做的,而且似乎运作良好

有人看到这个问题吗?

Friend Function everythingLinked(ByVal myClass As cls) As Boolean
    Dim q As New Queue(Of cls)(_clsCount)
    Dim found = False

    myClass.checked_link = true
    found = myClass.isMiddlePoint
    q.Enqueue(myClass)

    While Not found AndAlso q.Count > 0
        Dim p = q.Dequeue
        For i = 0 To p.numLink
            If Not found AndAlso masterArrayOfCls(myClass.linkNum(i)).checked_link = false Then
                masterArrayOfCls(myClass.linkNum(i)).checked_link = true
                found = masterArrayOfCls(myClass.linkNum(i)).isMiddlePoint
                q.Enqueue(masterArrayOfCls(myClass.linkNum(i)))
            End If
        Next
    End While
    q.Clear()

    Return found
End Function