![](/img/trans.png)
[英]Recursion - Exception in thread “main” java.lang.StackOverflowError
[英]Java - Recursion - Exception in thread “main” java.lang.StackOverflowError
嘗試打印出文件依賴項列表時遇到問題。
關於程序:
如果我了解地圖輸出的意思,則頭文件中會有一個循環(#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
地圖。 換句話說,避免循環的邏輯被打破了。
我建議您不要去研究自己喜歡的“數據結構和算法”教科書,而是在索引中查找“圖形遍歷”,而不是為您修改代碼。 另外,這是我在一些在線講義中找到的頁面:
Wikipedia和其他地方還涉及圖遍歷。 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)
測試依賴項是否已經打印的唯一地方是第一個for循環。 您也應該檢查第二個for循環!
for (String d : dependencies) {
if (!alreadyPrinted.containsKey(d)) {
LinkedList<String> key = theTable.get(d);
if (key != null)
output += printDependencies(theTable, key, alreadyPrinted);
}
}
一旦某些依賴項看起來像這樣,就很容易看到您的算法會遞歸:
item: ...., item, ....
(我聽到你說:“那不可能發生,因為...”。但是,SO表示確實發生了,或者堆棧太小了。)
順便說一句,您維護“已打印”地圖,但是沒有在哪里使用? 這暗示了您的實現中存在缺陷。
當您維護某種狀態(alreadyPrinted和輸出)時,我建議將狀態移至實例變量,並使用對象而不使用類方法。
問題是我的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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.