我在尝试打印出文件依赖项列表时遇到了问题。
关于该计划:
答案 0 :(得分:4)
如果我理解了地图输出的内容,那么头文件中就会有一个循环(#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
映射。换句话说,你的周期避免的逻辑被打破了。
我不打算为您修复代码,而是建议您转到自己喜欢的“数据结构和算法”教科书,并在索引中查找“图形遍历”。或者,这是我在一些在线讲义中找到的页面:
维基百科和其他地方的图遍历也有其他内容。 Google用于“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)
答案 1 :(得分:1)
测试依赖关系是否已经打印的唯一地方是第一个for循环。您也应该检查第二个for循环!
for (String d : dependencies) {
if (!alreadyPrinted.containsKey(d)) {
LinkedList<String> key = theTable.get(d);
if (key != null)
output += printDependencies(theTable, key, alreadyPrinted);
}
}
答案 2 :(得分:1)
一旦依赖性看起来很容易看到你的算法递归:
item: ...., item, ....
(我听到你说:“这不可能发生,因为......”然而,SO显示它确实发生了,或者你的堆栈太小了。)
顺便说一句,你保持地图“已经打印”,但它没有被使用?这暗示了您实施中的缺陷。
答案 3 :(得分:1)
当您维护某个状态(已打印和输出)时,我建议将状态移动到实例变量并使用对象而不使用类方法。
答案 4 :(得分:1)
问题是我的Graph遍历有我没有处理的循环。工作代码如下所示。
private static String printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, LinkedList<String> dependencies, ConcurrentHashMap<String, Boolean> alreadyPrinted) {
String output = "";
for (String d : dependencies) {
boolean isPrinted = alreadyPrinted.containsKey(d);
if (!isPrinted) {
output += " " + d;
alreadyPrinted.put(d, true);
}
}
for (String d : dependencies) {
LinkedList<String> key = theTable.get(d);
if (key != null) {
LinkedList<String> unvisited = new LinkedList<String>();
for (String filename : key)
if (!alreadyPrinted.containsKey(filename))
unvisited.add(filename);
if (unvisited != null)
output += printDependencies(theTable, unvisited, alreadyPrinted);
}
}
return output;
}
private static void printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, ConcurrentLinkedQueue<String> toProcess) {
String output = "";
for (String current : toProcess) {
ConcurrentHashMap<String, Boolean> alreadyPrinted = new ConcurrentHashMap<String, Boolean>(); // Keeps track of dependencies already printed
output += current + ":" + printDependencies(theTable, theTable.get(current), alreadyPrinted) + "\n";
}
System.out.println(output);
}