Java-递归-线程中的异常;“主要”;栈溢出

Java-递归-线程中的异常;“主要”;栈溢出,java,recursion,Java,Recursion,我在打印文件依赖项列表时遇到了一个问题 关于该计划: 扫描给定的*.c文件以查找依赖项,更具体地说是查找“#include”%” 找到这些文件并递归扫描它们的依赖关系 所有信息都存储在ConcurrentHashMap(键:字符串值:字符串链表)表中,其中字符串链表包含依赖项列表 在处理某个文件后,我得到以下哈希表: 测试依赖项是否已打印的唯一位置是第一个for循环。您也应该检查第二个for循环 for (String d : dependencies) { if (!alreadyPr

我在打印文件依赖项列表时遇到了一个问题

关于该计划:

  • 扫描给定的*.c文件以查找依赖项,更具体地说是查找“#include”%”
  • 找到这些文件并递归扫描它们的依赖关系
  • 所有信息都存储在ConcurrentHashMap(键:字符串值:字符串链表)表中,其中字符串链表包含依赖项列表
  • 在处理某个文件后,我得到以下哈希表:

  • 测试依赖项是否已打印的唯一位置是第一个for循环。您也应该检查第二个for循环

    for (String d : dependencies) {
        if (!alreadyPrinted.containsKey(d)) {
            LinkedList<String> key = theTable.get(d);           
            if (key != null)            
                output += printDependencies(theTable, key, alreadyPrinted);
        }
    }
    
    for(字符串d:依赖项){
    如果(!alreadyPrinted.containsKey(d)){
    LinkedList key=table.get(d);
    if(key!=null)
    输出+=打印依赖项(表、键、已打印);
    }
    }
    
    测试依赖项是否已打印的唯一位置是第一个for循环。您也应该检查第二个for循环

    for (String d : dependencies) {
        if (!alreadyPrinted.containsKey(d)) {
            LinkedList<String> key = theTable.get(d);           
            if (key != null)            
                output += printDependencies(theTable, key, alreadyPrinted);
        }
    }
    
    for(字符串d:依赖项){
    如果(!alreadyPrinted.containsKey(d)){
    LinkedList key=table.get(d);
    if(key!=null)
    输出+=打印依赖项(表、键、已打印);
    }
    }
    
    只要某些依赖项看起来像:

    item:  ...., item, ....
    
    (我听到你说:“那是不可能的,因为……”。然而,SO表明它确实发生了,或者你的堆栈太小了。)


    顺便说一句,您维护的映射“已打印”,但它没有被使用?这暗示着您的实现中存在缺陷。

    很容易看到,一旦某些依赖项看起来像:

    item:  ...., item, ....
    
    (我听到你说:“那是不可能的,因为……”。然而,SO表明它确实发生了,或者你的堆栈太小了。)


    顺便说一句,您维护的映射“已打印”,但它没有被使用?这暗示了您的实现中存在缺陷。

    当您维护某些状态(已打印和输出)时,我建议将状态移动到实例变量,并使用对象和非类方法。

    当您维护某些状态时(alreadyPrinted and output)我建议将状态移动到实例变量,并使用对象和非类方法。

    如果我理解映射输出的意思,则头文件中有一个循环(包含循环)

    i_50.h=[i_35.h, i_28.h, i_45.h, i_44.h, i_46.h],
    ....
    i_35.h=[i_50.h, i_51.h]
    
    这意味着您的依赖关系是一个图而不是DAG,这反过来意味着简单的递归遍历将不起作用

    从外观上看,您正在尝试进行图形漫游,但由于某些原因,您的循环检测/避免无法工作,并且您的算法进入“无限”递归


    查看代码后,我想我可以看到问题所在。在第一种方法中,您检查依赖项是否已打印,然后在
    alreadyPrinted
    映射中设置条目表示已打印。但是,您随后继续打印它,而不考虑它。然后在第二种方法中,您(莫名其妙地)已打印每次递归到第一个方法时,创建一个新的
    alreadyPrinted
    映射。换句话说,循环避免的逻辑被破坏


    与其为您修改代码,我建议您转到您最喜欢的“数据结构和算法”教科书,并在索引中查找“图形遍历”。或者,这里是我在一些在线课堂讲稿中找到的一页:

    维基百科和其他地方也有关于图遍历的内容。谷歌搜索“java递归图遍历”,并尝试找到对您有意义的东西

    一般算法如下所示:

        traverse(Node node):
            traverse_0(node, new Set<Node>())
    
        traverse_0(Node node, Set<Node> visited):
            if (visited.contains(node)) 
                return
            visited.add(node)
            for (Node child: node.children) 
                traverse_o(child, visited)
    
    遍历(节点):
    遍历0(节点,新集())
    遍历0(节点,访问集):
    if(已访问.包含(节点))
    返回
    已访问。添加(节点)
    for(节点子节点:Node.children)
    traverse_o(儿童,探访)
    
    如果我理解map输出的意思,那么头文件中有一个循环(include循环)

    i_50.h=[i_35.h, i_28.h, i_45.h, i_44.h, i_46.h],
    ....
    i_35.h=[i_50.h, i_51.h]
    
    这意味着您的依赖关系是一个图而不是DAG,这反过来意味着简单的递归遍历将不起作用

    从外观上看,您正在尝试进行图形漫游,但由于某些原因,您的循环检测/避免无法工作,并且您的算法进入“无限”递归


    查看代码后,我想我可以看到问题所在。在第一种方法中,您检查依赖项是否已打印,然后在
    alreadyPrinted
    映射中设置条目表示已打印。但是,您随后继续打印它,而不考虑它。然后在第二种方法中,您(莫名其妙地)已打印每次递归到第一个方法时,创建一个新的
    alreadyPrinted
    映射。换句话说,循环避免的逻辑被破坏


    与其为您修改代码,我建议您转到您最喜欢的“数据结构和算法”教科书,并在索引中查找“图形遍历”。或者,这里是我在一些在线课堂讲稿中找到的一页:

    维基百科和其他地方也有关于图遍历的内容。谷歌搜索“java递归图遍历”,并尝试找到对您有意义的东西

    一般算法如下所示:

        traverse(Node node):
            traverse_0(node, new Set<Node>())
    
        traverse_0(Node node, Set<Node> visited):
            if (visited.contains(node)) 
                return
            visited.add(node)
            for (Node child: node.children) 
                traverse_o(child, visited)
    
    遍历(节点):
    遍历0(节点,新集())
    遍历0(节点,访问集):
    if(已访问.包含(节点))
    返回
    已访问。添加(节点)
    for(节点子节点:Node.children)
    traverse_o(儿童,探访)
    
    问题是我的图形遍历有我没有处理的循环。工作代码是pr