在Java中,添加到变量不能正确使用递归调用
当我在一个图上实现一个桥接查找算法时,我偶然发现了一个错误,我的递归调用不能正确求和 如果您查看我在函数“root()”中的递归调用,则标记为“DOES WORK”的调用在终止后将索引为2的节点的“cnt”解析为2(正确答案),而工作不正常的调用则将“cnt”解析为4。我已经使用调试器试图找出问题所在,但问题是我认为我的代码没有任何问题。在某一点上,递归调用返回2,节点2的“cnt”值应为-1,但在添加错误的代码块后,“cnt”变为2而不是1 任何帮助都将不胜感激。我不确定这是java、我的IDE还是我自己的错误在Java中,添加到变量不能正确使用递归调用,java,Java,当我在一个图上实现一个桥接查找算法时,我偶然发现了一个错误,我的递归调用不能正确求和 如果您查看我在函数“root()”中的递归调用,则标记为“DOES WORK”的调用在终止后将索引为2的节点的“cnt”解析为2(正确答案),而工作不正常的调用则将“cnt”解析为4。我已经使用调试器试图找出问题所在,但问题是我认为我的代码没有任何问题。在某一点上,递归调用返回2,节点2的“cnt”值应为-1,但在添加错误的代码块后,“cnt”变为2而不是1 任何帮助都将不胜感激。我不确定这是java、我的ID
public class BridgeFind {
int N;
Node[] dfsTree;
boolean[] visited;
void init() {
dfsTree = new Node[N];
for (int i = 0; i < N; i++) {
dfsTree[i] = new Node();
}
visited = new boolean[N];
}
int root(int n, int p, int d) {
visited[n] = true;
dfsTree[n].d = d;
for (int ch : dfsTree[n].adj) {
if (ch != p) {
if (!visited[ch]) {
//DOES NOT WORK
dfsTree[n].cnt += root(ch, n, d+1);
//DOES WORK
int val = root(ch, n, d+1);
dfsTree[n].cnt += val;
} else if (dfsTree[n].d > dfsTree[ch].d){
dfsTree[n].cnt++;
dfsTree[ch].cnt--;
}
}
}
return dfsTree[n].cnt;
}
static class Node {
ArrayList<Integer> adj = new ArrayList<>();
int cnt = 0;
int d;
}
void add(int a, int b) {
a--;
b--;
dfsTree[a].adj.add(b);
dfsTree[b].adj.add(a);
}
void solve() {
N = 12;
init();
add(1, 3);
add(5, 3);
add(7, 5);
add(6, 3);
add(6, 2);
add(2, 8);
add(2, 4);
add(4, 10);
add(1, 9);
add(9, 11);
add(11, 12);
add(9, 12);
add(1, 6);
add(1, 5);
add(3, 7);
add(3, 8);
root(0, 0, 0);
visited = new boolean[N];
System.out.println(dfsTree[2].cnt);
}
public static void main(String[] args) {
BridgeFind next = new BridgeFind();
next.solve();
}
}
公共类BridgeFind{
int N;
节点树;
曾到访,;
void init(){
dfsTree=新节点[N];
对于(int i=0;idfsTree[ch].d){
dfsTree[n].cnt++;
dfsTree[ch].cnt--;
}
}
}
返回dfsTree[n].cnt;
}
静态类节点{
ArrayList adj=新的ArrayList();
int-cnt=0;
int d;
}
无效添加(内部a、内部b){
a——;
b--;
dfsTree[a].调整添加(b);
dfsTree[b].adj.add(a);
}
void solve(){
N=12;
init();
添加(1,3);
添加(5,3);
添加(7,5);
增加(6,3);
增加(6,2);
添加(2,8);
添加(2,4);
添加(4,10);
添加(1,9);
增加(9、11);
增加(11、12);
增加(9、12);
添加(1,6);
添加(1,5);
添加(3,7);
添加(3,8);
根(0,0,0);
已访问=新布尔值[N];
System.out.println(dfsTree[2].cnt);
}
公共静态void main(字符串[]args){
BridgeFind next=新建BridgeFind();
next.solve();
}
}
虽然这两个代码片段表面上看起来很相似,但实际上并不是做同一件事
此块首先计算root(ch,n,d+1)
(它修改dfsTree[n].cnt
),然后将返回值添加到dfsTree[n].cnt的新值中
int val = root(ch, n, d+1);
dfsTree[n].cnt += val;
另一方面,此行首先捕获dfsTree[n].cnt的值,然后计算root(ch,n,d+1)
(它修改dfsTree[n].cnt
),将返回值添加到dfsTree[n].cnt的原始值中并存储它,它将覆盖对根(ch,n,d+1)
的调用中发生的修改
编辑
如果您想要一个不依赖临时变量的单行解决方案,您可以通过编写标准赋值来强制计算顺序x+=y
是x=x+y
的简写,但是如果您需要先计算y
,您可以简单地将其写成x=y+x
e、 g
结果是程序输出为2
虽然这两个代码片段表面上看起来很相似,但实际上它们并不是在做相同的事情
此块首先计算root(ch,n,d+1)
(它修改dfsTree[n].cnt
),然后将返回值添加到dfsTree[n].cnt的新值中
int val = root(ch, n, d+1);
dfsTree[n].cnt += val;
另一方面,此行首先捕获dfsTree[n].cnt的值,然后计算root(ch,n,d+1)
(它修改dfsTree[n].cnt
),将返回值添加到dfsTree[n].cnt的原始值中并存储它,它将覆盖对根(ch,n,d+1)
的调用中发生的修改
编辑
如果您想要一个不依赖临时变量的单行解决方案,您可以通过编写标准赋值来强制计算顺序x+=y
是x=x+y
的简写,但是如果您需要先计算y
,您可以简单地将其写成x=y+x
e、 g
结果程序输出为2
谢谢!事实上,这很有道理。为了确保我的理解是正确的,如果我编写了dfsTree[n]=root(ch,n,d+1)+dfsTree[n],那么代码将按预期工作,因为首先计算root()?正确。我已经更新了我的答案,让它更明确。谢谢!事实上,这很有道理。为了确保我的理解是正确的,如果我编写了dfsTree[n]=root(ch,n,d+1)+dfsTree[n],那么代码将按预期工作,因为首先计算root()?正确。我已经更新了我的答案,使之更加明确。
dfsTree[n].cnt = root(ch, n, d+1) + dfsTree[n].cnt;