在Java中,添加到变量不能正确使用递归调用

在Java中,添加到变量不能正确使用递归调用,java,Java,当我在一个图上实现一个桥接查找算法时,我偶然发现了一个错误,我的递归调用不能正确求和 如果您查看我在函数“root()”中的递归调用,则标记为“DOES WORK”的调用在终止后将索引为2的节点的“cnt”解析为2(正确答案),而工作不正常的调用则将“cnt”解析为4。我已经使用调试器试图找出问题所在,但问题是我认为我的代码没有任何问题。在某一点上,递归调用返回2,节点2的“cnt”值应为-1,但在添加错误的代码块后,“cnt”变为2而不是1 任何帮助都将不胜感激。我不确定这是java、我的ID

当我在一个图上实现一个桥接查找算法时,我偶然发现了一个错误,我的递归调用不能正确求和

如果您查看我在函数“root()”中的递归调用,则标记为“DOES WORK”的调用在终止后将索引为2的节点的“cnt”解析为2(正确答案),而工作不正常的调用则将“cnt”解析为4。我已经使用调试器试图找出问题所在,但问题是我认为我的代码没有任何问题。在某一点上,递归调用返回2,节点2的“cnt”值应为-1,但在添加错误的代码块后,“cnt”变为2而不是1

任何帮助都将不胜感激。我不确定这是java、我的IDE还是我自己的错误

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;