您好我有一棵树,我希望从初始(根)节点到所有叶子获取路径。
我发现了几个算法列出了(在图表中任何给定的两个节点之间的所有)apths(例如这个SO问题: Graph Algorithm To Find All Connections Between Two Arbitrary Vertices)
对于二叉树,还存在一种算法 http://techieme.in/print-all-paths-in-a-tree/ 但我在一棵树上工作,有各种分支因素。
有没有更好的方法来实现我想做的事情,而不是遍历树一次以获得所有叶子,然后针对所有叶子和初始节点运行上面的算法?
我正在考虑实现一些额外堆栈扩展的简单DFS,其中包含沿着路径到达单个叶子的所有节点,然后通过循环遍历这些堆栈来列出所有句子。
ArrayList<GrammarNode> discovered = new ArrayList<GrammarNode>();
Stack<GrammarNode> S = new Stack<GrammarNode>();
while (!S.empty()) {
node = S.pop();
if (!discovered.contains(node)) {
discovered.add(node);
System.out.println(node.getWord.getSpelling().trim());
for (GrammarArc arc : node.getSuccessors()) {
S.push(arc.getGrammarNode());
}
}
}
更新 这个问题是,为了生成完整的句子,人们会回到根。所以我想问题是:如何记住已经完全访问过的节点(这意味着已经探索过所有子节点)?
答案 0 :(得分:3)
打印从根到每个叶子的所有路径意味着打印整个树,所以我只使用一个简单的DFS并为每个节点执行以下操作:
示例:
A
/ \
B E
/ \ / \
C D F G
第一步看起来像这样:
答案 1 :(得分:0)
如果您知道图形确实是一个树(每个节点只有一条路径),它们是的,简单的DFS会更有效(至少从内存使用的角度来看)。否则,您也可以使用iterative deepening DFS。
答案 2 :(得分:0)
所以这是一个示例方法。请注意,您的节点结构中需要额外的visited
字段:
public class TreeNodeExtra {
int val;
TreeNodeExtra left;
TreeNodeExtra right;
boolean visited;
TreeNodeExtra (int v) {
val = v;
visited = false;
}
}
private ArrayList<ArrayList<TreeNodeExtra>> all_path_from_root_to_leaf(TreeNodeExtra root) {
Stack<TreeNodeExtra> st = new Stack<>();
ArrayList<ArrayList<TreeNodeExtra>> res = new ArrayList<>();
st.push(root);
root.visited = true;
while (!st.isEmpty()) {
TreeNodeExtra top = st.peek();
if (top.left != null && !top.left.visited) {
st.push(top.left);
top.left.visited = true;
}
// if left node is null
else {
if (top.right == null && top.left == null) {
// we have a leaf
ArrayList<TreeNodeExtra> tmpList = new ArrayList<>();
for (TreeNodeExtra t : st) {
tmpList.add(t);
}
res.add(tmpList);
st.pop();
}
else if (top.right != null && !top.right.visited) {
st.push(top.right);
top.right.visited = true;
}
else {
st.pop();
}
}
}
return res;
}
答案 3 :(得分:0)
略微修改DFS(包括反向跟踪)会打印来自给定源的所有路径。在下面的示例中,图表以邻接列表格式表示。
public void mDFS(ArrayList<node> v,int ind,ArrayList<Boolean> visit,ArrayList<node> tillNow){
visit.set(ind,true);
node n = v.get(ind);
int len = n.adj.size();
tillNow.add(n);
int count = 0;
for(node tmp: n.adj){
if( !visit.get(tmp.id) ){
count++;
tmp.pre = ind;
mDFS(v,tmp.id,visit,tillNow); // id gives index of node in v
}
}
if(count == 0){
for(node tmp: tillNow){
System.out.print((tmp.id + 1) + " - ");
}System.out.print("\n");
}
visit.set(ind,false);
tillNow.remove(tillNow.size() - 1);
return;
}