Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 一种递归算法的调试_Java_Debugging_Recursion - Fatal编程技术网

Java 一种递归算法的调试

Java 一种递归算法的调试,java,debugging,recursion,Java,Debugging,Recursion,我的问题是,是否有一些聪明的方法来调试复杂的递归算法。 假设我们有一个复杂的例子(不是递归计数器在每个“嵌套迭代”中减少的简单例子) 我的意思是,当循环是可能的时候,类似于递归遍历一个图 我需要检查我是否在某个地方得到了无止境的循环。仅仅使用调试器并不能给出确定的答案(因为我不确定一个算法是在无休止的循环中,还是只是它应该进行的处理) 没有具体的例子很难解释。但我需要的是 '检查无止境循环是否在复杂的递归算法中发生。如果要检查无止境循环 编写一个System.out.println(“不,它不是

我的问题是,是否有一些聪明的方法来调试复杂的递归算法。 假设我们有一个复杂的例子(不是递归计数器在每个“嵌套迭代”中减少的简单例子)

我的意思是,当循环是可能的时候,类似于递归遍历一个图

我需要检查我是否在某个地方得到了无止境的循环。仅仅使用调试器并不能给出确定的答案(因为我不确定一个算法是在无休止的循环中,还是只是它应该进行的处理)

没有具体的例子很难解释。但我需要的是


'检查无止境循环是否在复杂的递归算法中发生。

如果要检查无止境循环

编写一个
System.out.println(“不,它不是无止境的”)位于调用递归函数的下一行


如果循环是无止境的,则此语句不会打印,否则您将看到输出

建议如下:

如果有无穷循环,则在图的情况下,将获得顶点数大于图中顶点总数的路径。假设图中的顶点数是一个全局变量(我认为这是最常见的情况),如果深度已经超过顶点总数,则可以在递归开始时执行条件断点


如何在Eclipse中为java创建条件断点

您需要计算递归调用的深度。。。然后,如果递归调用的深度达到某个阈值,则抛出异常

例如:

void TheMethod(object[] otherParameters, int recursiveCallDepth)
{
   if (recursiveCallDepth > 100) { 
      throw new Exception("...."); }
   TheMethod(otherParameters, ++recursiveCallDepth);
}
最好的方法是通过前置和后置条件、变量和不变量来证明有限性。如果您可以指定一个(虚拟)公式,该公式的值在每次调用时都会增加,那么您就有了保证


这与证明循环是有限的是一样的。此外,它可能使复杂的算法更容易处理。

你需要形成一个理论,解释为什么你认为算法会终止。理想情况下,将理论证明为数学定理

您可以查找问题状态的函数,该函数在每次递归调用时都会减少。例如,请参见以下关于Ackermann函数的讨论,来自

A(m,n)的求值总是终止,这可能不是很明显。但是,递归是有界的,因为在每个递归应用程序中,m减小,或者m保持不变,n减小。每次n达到零,m都会减小,所以m最终也会达到零。(更严格地说,在每种情况下,对(m,n)在对上的字典顺序中都会减少,这是一种良好的顺序,就像单个非负整数的顺序一样;这意味着一个人不能在顺序中连续无数次下降。)然而,当m减小时,n的增加量没有上限,而且通常会大大增加

这是您应该考虑应用于算法的推理类型


如果找不到任何方法来证明算法终止,请考虑寻找一个可以终止的变量。决定一个任意程序是否终止并不总是可能的。诀窍是编写可以证明终止的算法。

使用打印语句进行调试?我试过了。但它会减慢执行速度(非常慢),所以几分钟后,我不知道算法是否还在处理(像它应该的那样),或者只是它已经在无休止的循环中了递归迭代的对象空间“巨大”,减少嵌套逻辑并不简单(不是每次迭代都减少一个)。在简单的情况下,算法运行良好。为什么不发布算法?伪代码?任何东西这个问题非常模糊,正确的答案取决于许多因素。不是这样,循环可能在经过许多路径后才被观察到。@BorisStrandjev,我真的不明白你的意思。如果程序是这样的
调用递归函数()
那么如果在下一行我写
System.out.println(“”),我认为除非上述函数返回一个值,即退出递归,否则SOP不会执行映射DFS递归实现。在遇到第一个循环之前,它可以遍历几个简单的路径,这可能是唯一的失败。若你们需要我,我可以给你们提供代码。@BorisStrandjev:是的,我知道路径可能会进入循环。请给我提供代码,如果你认为我建议将
SOP
放在哪里,我仍然不明白我的建议怎么会失败。谢谢:)@MukulGoel你怎么能证明你没有得到预期的system.out不是因为算法处于无限循环中,而是因为它仍在处理中?这不是一个解决方案——可能在一些简单的情况下。这在某些情况下可能有效,但不是对老年退休金问题的具体回答。高度依赖于问题的上下文。@AlexLynch和也是我断点建议的一个抛出变量,顺便说一句,我不确定这是否更好。最终您将遍历顶点数大于顶点总数的路径。也许OP的投入太大了,这是不可行的。如果这不是一个超级秘密的
复杂的
算法,我会说,根据算法之前遍历的位置,很容易检测出算法是否陷入循环。但谁知道op真正需要什么。也许OP可以多次跨越某些节点,而不会陷入循环(这打破了你的想法),在我的例子中,它并不是那么简单。首先,我的图表不是常数。算法应该适用于不同的图。图没有固定的结构。节点之间的连接可能取决于节点中的某些值。此外,节点可以被多次访问。@ukaszRzeszotarski当然-我的解决方案适用于一般图形,由用户动态输入。您可以轻松地使条件断点依赖