我对http://visualbasic.about.com/b/2007/06/06/permutations-recursion-and-traversing-a-binary-tree.htm修改过的方法感到茫然不知所措。我在VB.net中重写了它,虽然看起来好像需要大量的循环才能完成任务。
这个方法接受一个单词,并返回该单词中字母的所有变体,沿着它只显示字典中出现的单词的方式,但这不是问题。
一旦通过单词中的字母如abcd,循环通过a,ab,abc等,它就会到达end sub。
我希望它会停止。但事实并非如此,这就是我感到困惑的一点。它返回到递归调用并再次从那里运行代码到end sub,多次。如果有什么我会期望它回到sub的顶部,这本身就是奇怪的,但在递归调用之后不会回到。它不会遍历整个潜艇,看起来就像从那里开始。
SUBSECTION OF CODE
PermutationOfLetters()
' Mark this item free again - start again
IsItemUsed(i) = False
' Restore the current Perm
permutationString = PermWord
End If
Next
BGworker.ReportProgress(LoopCounter)
End Sub
它需要这样做以使分支工作,但我不知道是什么使它做到这一点? 任何人都可以开导我吗?这让人很难解释“巫毒发生在这里”。
我刚注意到链接上的另一张海报,原始代码问了同样的问题。 : - )
所有代码
Private Sub PermutationOfLetters()
'Just a counter to see how many time the Sub loops
Static RecursionCounter As ULong = 0
' lbxWords.Items.Add("recursion " & RecursionCounter)
RecursionCounter += 1
'Just a counter to count how many loops in the For statement
Static LoopCounter As ULong = 0
'chop up the word into a character array w,o,r,d,s
Static WordIntoletters As Char() = myDictionary.SelectedWord.ToCharArray()
Static permutationString As String
' gives a true /false for each letter as it passes through set false to start - Boolean Array
Static IsItemUsed(myDictionary.SelectedWord.Length - 1) As Boolean
Dim PermWord As String = permutationString ' Save the current Perm for each value currently available
'count through each letter and operate on those that are false
For i = 0 To myDictionary.SelectedWord.Length - 1
LoopCounter += 1
'when it finds a false then run the loop
If IsItemUsed(i) = False Then
'add another letter to the word
permutationString += WordIntoletters(i)
If FoundWordsDictionary.ContainsKey(permutationString) = False Then
End If
'if words are in the dictionary output real words and are not already saved
If myDictionary.WordDictionary.ContainsKey(permutationString) = True AndAlso FoundWordsDictionary.ContainsKey(permutationString) = False Then
' lbxWords.Items.Add(i & " " & permutationString)
'pass the words through to the sorted dict for easy output
FoundWordsDictionary.Add(permutationString, permutationString)
' lbxWords.Items.Add(permutationString)
End If
' Mark this item unavailable - finished with a true
IsItemUsed(i) = True 'so don't come back to that letter
PermutationOfLetters()
' Mark this item free again - start again
IsItemUsed(i) = False
' Restore the current Perm
permutationString = PermWord
End If
Next
BGworker.ReportProgress(LoopCounter)
End Sub
答案 0 :(得分:2)
您似乎对递归意味着什么感到困惑。当您以递归方式调用方法时,这意味着方法会调用自身。这样做,它就像调用不同的方法时一样。例如:
Public Sub Method1()
Console.WriteLine("Begin 1")
Method2()
Console.WriteLine("End 1")
End Sub
Public Sub Method2()
Console.WriteLine("2")
End Sub
希望当您在上面的示例中调用Method1
时,它将输出以下行并不奇怪:
开始1
2
结束1
当执行Method2
时,它会继续到下一行(Console.WriteLine("End 1")
)。你肯定不希望执行在那时跳回到Method1
的顶部。
递归以相同的方式工作,但是在调用堆栈中不是两种不同的方法,而是在调用堆栈中重复多次相同的方法。调用堆栈上方法的每个“实例”都维护它自己的执行位置(这就是为什么它被称为堆栈)。当前对方法的调用状态保持在堆栈中,而对方法的下一次调用则在堆栈上添加。一旦执行完内部方法调用,堆栈就会回退到前一个方法,该方法从中断的位置开始。
对方法的每次调用都有自己的局部变量值的独立副本。虽然在这种情况下,它将许多局部变量定义为Static
,这意味着这些变量的值将在调用堆栈中对该方法的所有调用中共享。