我相信我在编程方面有很好的背景,但今天我遇到了一些令我质疑的东西。这是代码:
public class Recursive{
public static void main(String[] args) {
func(10);
}
static void func(int x)
{
if(x > 0)
{
func(x/2);
System.out.print(x % 2); // I thought the code won't reach here ever
}
}
}
在我看来,这段代码不应该打印任何东西。但它在我编译时实际打印1010
。如果System.out.print(x % 2)
是在func(X/2)
之前编写的,那么它会有意义,但现在看起来不对。对此有何解释?
答案 0 :(得分:2)
调用func然后打印x%2。
另一方面,如果使用return func(x / 2),则永远不会达到print语句。
答案 1 :(得分:2)
简单。首先,函数func()获取值10。
在内部,它检查是否10> 0.因为它是,它调用func(5 /*10/2 = 5*/
)。
然后,因为5> 0,在内部调用func(2)。这是因为.5的截断。
调用func(2/2 /*= 1*/)
并执行。
然后,调用返回的func(0)。当它返回时,Print语句以1%2 = 1执行。在内部返回并且再次执行print语句,2%2 = 0.再次返回并再次执行print语句,参数5%2 = 1。返回最后一个print语句再次执行打印0。
答案 2 :(得分:1)
它必须对func进行第二次调用,然后调用已完成,它将在堆栈中完成原始函数。
你需要查找基本的递归理论。
http://en.wikipedia.org/wiki/Recursion_(computer_science)。
如上所述,使用 return func(x / 2) 将从堆栈中删除该函数,因此永远不会到达函数的末尾。
答案 3 :(得分:1)
func(x/2); ----------------> // Statement # 1
System.out.print(x % 2); ------> // Statement # 2
Statement # 2
如果您返回 Unreachable Block
的值,则 func(x / 2) call
的 Statement # 1
强>
Recursive function calls
存储在stack
上。因此,对于每次调用,都会生成stack entry
,存储当前呼叫,然后转向下一个呼叫。
现在,当达到你的基本条件时,stack
开始roll-back
,通过弹出函数的先前状态,然后最终到达它开始的位置。
现在,在从堆栈中弹出每个func
调用之后,继续执行function
中最后一次func()
调用(Statement # 2 in this case)
的下一个语句,并且完成后,该函数返回,然后在堆栈上调用下一个函数。 (注意: - 如果你有return func(x / 2)
代替func(x / 2)
,那么代码将不会执行下一个语句,而是立即控制堆栈中的下一个函数。因此{{1} } 强>)
最后声明
Unreachable Code
当System.out.print(x % 2);
完全清空时,将被执行,并且控件返回
stack
函数调用,位于堆栈的底部。
所以,你的递归是这样的: -
筹码: -
func(x / 2)
假设func(x / 8) --> Base condition
func(x / 4) ^
func(x / 2) ^
func(x) --> First invocation
是基本条件。因此,当x / 8
完成执行时,执行的下一个语句是: -
func(x / 8)
- >此处x的值为 System.out.println(x % 2)
然后从堆栈中弹出此函数,并将控件返回到堆栈中的下一个函数: - original-x / 8
,然后执行下一个语句: -
func(x / 4)
- >这里System.out.println(x % 2)
再次 x
等等。最后,original-x / 4
执行 System.out.println(x % 2)
答案 4 :(得分:1)
打印零和零的行为绝对正确。
虽然你的x>严格大于0,但你会用新的x = int(x / 2)进行更深入的递归,因为x是一个整数。
当x <= 1时,你将有x / 2 == 0因此递归停止,你将开始打印x / 2的余数。
在你的情况下:
f(10)->f(5)->f(2)->f(1)->f(0)
|
0 <- 1 <- 0 <- 1 <-+
提示:当我遇到这种问题时,我会在代码中放置System.out.println()跟踪以了解流程。如果您使用的是Eclipse / Netbeans / Idea,则可以进入调试模式并单步执行代码。
答案 5 :(得分:0)
好的技巧问题