給定一個定向樹T,每個節點的子節點數量可變,我想從根開始找到一個PATH_SIZE大小的「好」節點的路徑。Javascript:對涉及I/O的定向樹的DFS遍歷
每個節點都有一個isGood()
方法和一個getChildren()
方法,按預期工作。
一個簡單的DFS遞歸的解決方案是這樣的:(請糾正我,如果我錯了)
function findGoodPath(node, depth){
if(!node.isGood()){
return null;
} else if (depth==PATH_SIZE){
return [node];
}
var children = node.getChildren();
for (var i=0; i<children.length; i++){
var result = findGoodPath(children[i], depth+1);
if (result){
return result.concat([node]);
}
}
return null;
}
調用findGoodPath(root, 1)
如果存在的話應該找的結果。
現在爲問題:節點對象的getChildren()
方法實際上是一個異步方法,它在後臺執行I/O操作。它不會返回任何內容,並且需要一個回調參數來處理返回的子項。
一個修改後的代碼的解決方案(這是WRONG)可以是這樣的:
function findGoodPath(node, depth){
if(!node.isGood()){
return null;
} else if (depth==PATH_SIZE){
return [node];
}
node.getChildren(function(children){
for (var i=0; i<children.length; i++){
var result = findGoodPath(children[i], depth+1);
if (result){
return result.concat([node]);
}
}
});
}
該解決方案將無法正常工作:單個節點的孩子所有的getChildren方法將被調用一次,所以它實際上會執行一個BFS。更糟糕的是,返回語句與匿名回調函數相關聯,並在封閉函數完成運行後執行。
很明顯,需要某種流量控制機制。什麼是這個問題的簡單而優雅的解決方案?
更新:我接受了塞巴斯蒂安的答案,因爲它解決了遞歸問題,這就是我提出問題的方式。我還發布了一個使用async's庫whilst循環的答案,這是我最終使用的。 Sebastien非常友好地以這兩種方法爲基準here。(擾流板:性能相同)
感謝塞巴斯蒂安,優秀的言論! –
我的不好,當然這個函數需要有一個回調參數。非功能性代碼示例只是爲了展示將此轉換爲異步的一些問題。我會在早上看看它,但是我目前的方向是轉移到非遞歸解決方案,然後使用js異步庫中的函數來控制流。結合異步函數和遞歸是一個很好的挑戰,但我擔心它會創建不可維護的代碼(至少對我而言)。 –
真的!但能夠以異步的方式做到這一點非常有效,肯定是一個很好的挑戰:) –