java - DFS 未正确执行

标签 java algorithm depth-first-search tree-traversal

我要解决this problem ,但我被困在问题的一小部分上。简而言之,给定一棵树,这棵树的每个顶点都有一些权重。我们将一棵树的总和定义为树中包含的所有节点的所有权重的总和。

我有 N 个节点,我想计算以这 N 个节点中的每一个节点为根的子树的总和。我想将这个总和存储在数组 res[] 中。为此,我必须执行 DFS 并正确总结节点的权重。但是,我的 DFS 不是这样工作的,我不知道如何纠正它。

编辑:我调试了我的代码,但我不知道如何更正它。它无法计算叶子的 res[] 值(对于它们,它不返回任何内容)。此外,它不会为内部节点计算正确的值。我以为我必须在 dfs 方法中定义新变量 int tempRes 并返回这个变量,但在某些时候我必须将它归零,但我没有知道在哪里。

package searching;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class CutTheTree {

    static List<ArrayList<Integer>> adj; //list which stores adjacency nodes, i.e. at position i I have list of the neighbours of node i
    static int N; //number of nodes
    static int[] res; //store the sum of weights of tree rooted at node i
    static boolean[] visited; //array which indicates if I have visited node or not
    static int[] weights;   //array of the given weights of each node
    static int W;   //this variable is not relevant to my problem

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line1 = br.readLine();
        N = Integer.parseInt(line1);
        String[] line2 = br.readLine().split(" ");
        weights = new int[N];       //weights of each vertex
        visited = new boolean[N];
        res = new int[N];
        adj = new ArrayList<ArrayList<Integer>>(N);
        for (int i = 0; i < N; i++) {
            adj.add(i, new ArrayList<Integer>());
        }
        for (int i = 0; i < line2.length; i++) {
            weights[i] = Integer.parseInt(line2[i]);
        }
        W = 0; //total sum
        for (int i = 0; i < weights.length; i++) {
            W+= weights[i];         //total sum of all weights
        }
        for (int i = 0; i < N-1; i++) { //follow N-1 lines of the edges given as pairs, i.e. (1, 3) means edge from vertex 1 to vertex 3
            String[] line3 = br.readLine().split(" ");
            int start = Integer.parseInt(line3[0]);
            int end = Integer.parseInt(line3[1]);
            adj.get(start-1).add(end);      //store adjacent nodes in a linked list; substract 1 from the vtx id, since the indexing starts from 0
            adj.get(end-1).add(start);      //example: vtx 1 is a neighbor of vtx 3 and vtx 3 is neigbor of vtx 1
        }
        dfs(1);     //take vtx one as a root
        for (int i = 0; i < N; i++) {
            System.out.print(res[i] + " ");
        }

    }

    // The problematic function!!!
    private static int dfs(int root) {
        int temp;
        Stack<Integer> st = new Stack<Integer>();
        ArrayList<Integer> neigh = new ArrayList<Integer>(); //list of unvisited neighoring vetrices of the current node
        st.push(root);
        visited[root-1] = true; //mark current node as visited
        while(!st.isEmpty()){
            int curr = st.pop();
            if(isLeaf(curr)){
                res[curr-1]= weights[curr-1];
                return weights[curr-1];
            }
            else{
                neigh = neighbours(curr);
                if(neigh.size() == 0){
                    temp = weights[curr-1]; //if there is no unvisited nodes, return the weight function of the given node; however this does not work for the leaf nodes!                  
                }
                else{ //else I have to visit unvisited neighbors
                    res[curr-1] = weights[curr-1]; //the current res increases by the weight of the given node
                    for (int i = 0; i < neigh.size(); i++) {
                        int child = neigh.get(i);
                        visited[child-1] = true;
                        st.push(child);
                        res[curr-1]+= dfs(child); // for each unvisited neighbor I perform dfs and add the result to the corresponding index of res array
                    }
                }
            }
        }
        return 0;
     //returns ArrayList of unvisited nodes of the current node
    private static ArrayList<Integer> neighbours(int node){
        ArrayList<Integer> res = new ArrayList<Integer>();
        for (int i = 0; i < adj.get(node-1).size(); i++) {
            int child = adj.get(node-1).get(i);
            if(!visited[child-1]){
                res.add(child);
            }
        }
        return res;
    }
}

最佳答案

您的 dfs 方法返回 0,叶节点除外。

此外,您似乎将递归和迭代方法混合在一起。如果您使用自己的未访问节点堆栈,则无需依赖递归提供的调用堆栈。

基本上,您需要访问每个节点。在每次访问中,您将节点的权重添加到单个总和中,然后将其子节点添加到堆栈中。

int result = 0;

while(!st.isEmpty()){
    int curr = st.pop();
    neigh = neighbours(curr);
    result += weights[curr-1]; 
    if(neigh.size() != 0){
        for (int i = 0; i < neigh.size(); i++) {
            int child = neigh.get(i);
            visited[child-1] = true;
            st.push(child);
        }
    }
}

return result;

关于java - DFS 未正确执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24786353/

相关文章:

java - GIWS 在构建类时终止进程

java - 我可以在 Java 中模拟 protected 父类(super class)方法调用吗?

java - 之后使用 switch 分割字符串

c++ - 如何理解频率图像中描述的平均像素数?

sql-server-2008 - 如何在深度优先搜索中正确标记树的分支

java - 使用代理记录 jmeter 请求不会创建采样器

sql - 使用 SQL 查询进行轮盘赌选择

c - 优化选择排序?

algorithm - DFS 递归与 DFS 迭代

c - 删除和 DFS 功能无法正常工作