如何获取从根到二叉树上给定节点的路径?
Posted
技术标签:
【中文标题】如何获取从根到二叉树上给定节点的路径?【英文标题】:how to get the path from root to a given node on a binary tree? 【发布时间】:2011-09-09 00:26:43 【问题描述】:我正在尝试找出如何获取从根到二叉树上给定节点的路径。
它不是二叉搜索树。
每个非叶节点只有两个指向其子节点的指针。
按序、前序、后序遍历不起作用。
我尝试过预订,但不知道怎么做。例如,我们有一棵二叉树: 它不是二叉搜索树。我们使用排序节点来更容易找到路径。
1
/ \
2 3
/ \ / \
4 5 6 7
我们要找到从 1 到 7 的路径:
通过预购,我们有:
1 -> 2 -> 4 -> 5 -> 3 -> 6 -> 7
从流程中,我们得到从 1 -> 7 的路径,其中包含所有节点。
显然,不应该。
非常感谢任何帮助。
【问题讨论】:
Find path to node in Tree?的可能重复 【参考方案1】:前序遍历,也称为深度优先搜索确实有效。
如果您以递归方式实现前序遍历,那么当您到达所需节点时,您可以展开(递归调用的)堆栈并反向构建路径。
如果您以非递归方式实现前序遍历,那么您将直接构建堆栈,因此在这种情况下,一旦您到达所需的节点,您就已经有了自己的路径。
在上述问题的树中,查找从 1 到 7 的路径的算法如下。
从 1 开始,将其压入堆栈,堆栈现在为 [1] 向左移动到 2,将其压入堆栈,堆栈现在是 [1 2] 向左到 4,推它,堆栈现在是 [1 2 4] 没有 4 的孩子,而且不是你想要的,所以弹出它,堆栈现在是 [1 2] 现在您回到了 2,并且您已经向左走,现在向右走,堆栈现在是 [1 2 5] 没有 5 的孩子,所以 pop,堆栈现在是 [1 2] 你已经用尽了 2 的孩子,所以弹出它,堆栈现在是 [1] 现在你回到了 1 并且你已经完成了左边,所以向右走到 3,推它,堆栈现在是 [1 3] 向左走,堆栈现在是 [1 3 6] 6 是叶子,不是你要找的,所以 pop,stack 是 [1 3] 现在你必须从 3 向右推,堆栈现在是 [1 3 7] 但是等等!看!您已到达您要查找的节点!看看你的堆栈!这是您想要的路径。【讨论】:
我试过这样做,但不知道怎么做。例如,我们有一棵二叉树:它不是二叉搜索树。我们使用排序节点来更容易找到路径。 1 2 3 4 5 6 7 我们想找到从 1 到 7 的路径:通过预购,我们有: 1 -> 2 -> 4 -> 5 -> 3 -> 6 -> 7 从流程中,我们从 1 -> 7 获取所有节点的路径。显然,它不应该。非常感谢任何帮助。 @dtustudy68,好的,我已经更新了我的答案。如果您想查看以特定编程语言(Ruby、Python、javascript,首选)实现的算法,请告诉我。 能否请您看看这个解决方案,以及您的意见?正如您所建议的,它也由 DFS 实现。链接:codereview.stackexchange.com/questions/105136/… 这是一种典型的预排序非递归方法,但我认为它无法生成路径。def nlr(root): stack = [] node = root while node or stack: if node: print node.val stack.append(node) node=node.left else: node = stack.pop() node = node.right
。此刻,我们转到5,堆栈应该是[1],而不是[1,2],因此,无法生成路径。
我不喜欢这个实现的原因是它需要一个“已访问”属性。通常,您会在遍历其子树的右侧之前弹出根节点,因此在前序遍历中它不会在您的堆栈中。例如,你怎么知道你已经用尽了 2 的孩子【参考方案2】:
给你一棵二叉树(根节点).. 并且给定一个键,它可能在树中,也可能不在树中。 您必须找到从根到节点的完整路径。
例子:
A
/ \
B C
\ /
D E
/ \ \
K L M
/
Z
您已经给定节点 Z(或节点的键)并给定节点 A(root) 所以你的输出应该是
A B D K Z
如果给定 M,输出应该是 A C E M
public class main_class
public static void main(String args[] )
//first create tree
Node rootNode = new Node ('A' , new Node('B',null,
new Node('D',
new Node('K',
new Node('Z',null,
null),null),
new Node('L',null,null))),
new Node('C',
new Node('E',
null,
new Node('M',null,null)),null) );
ArrayList <Node> path = new ArrayList<Node>();
System.out.println(getPath(rootNode,'Z',path));
System.out.println(path);
path = new ArrayList<Node>();
System.out.println(getPath(rootNode,'M',path));
System.out.println(path);
static boolean getPath(Node rootNode, char key, ArrayList<Node> path )
//return true if the node is found
if( rootNode==null)
return false;
if (rootNode.getVal()==key)
path.add(rootNode);
return true;
boolean left_check = getPath( rootNode.left,key,path);
boolean right_check = getPath( rootNode.right,key,path);
if ( left_check || right_check)
path.add(rootNode);
return true;
return false;
static class Node
char val;
Node left;
Node right;
public Node( char val, Node left, Node right)
this.left=left;
this.right=right;
this.val=val;
public char getVal()
return val;
public String toString()
return " " + val + " ";
【讨论】:
【参考方案3】:考虑以下树:
10
/ \
8 2
/ \ /
3 5 2
接近
我们从根开始并将其与键进行比较,如果匹配则打印路径(如果树只有一个节点,则路径仅包含根)。 否则将节点推入 Vector(我考虑使用向量来存储路径)。 递归遍历树的左右。以下代码会有所帮助:
void PrintPath(node* root, vector <int> v,int key)
if(!root)
return;
if(root->data==key)
v.push_back(root->data);
vector<int>:: iterator it;
for(it=v.begin();it<v.end();it++)
cout<<*it<<" ";
return;
v.push_back(root->data);
PrintPath(root->left,v,key);
PrintPath(root->right,v,key);
说明
让要找到的节点是给定树的 5(key)。
每一步向量的内容:
-
V = 10
V = 10,8
V = 10,8,3(3不是要找到的关键,所以我们会回溯向右)
V = 10,8,5(5 是键,因此打印路径)。
【讨论】:
【参考方案4】:这里有 3 个 Java 解决方案:https://codereview.stackexchange.com/questions/105136/path-sum-in-binary-tree 第一种是递归方法,第二种是使用 2 个 satcks,最后一种是使用 2 个队列。希望这会有所帮助
【讨论】:
【参考方案5】:public List<Node<T>> getPath(T data)
Stack<Node<T>> stack = new Stack<Node<T>>();
Boolean found = getPath(root, stack, data);
List<Node<T>> path = new ArrayList<Node<T>>();
if(!found)
return path;
return Arrays.asList(stack.toArray((Node<T>[])new Node[stack.size()]));
public Boolean getPath(Node<T> node, Stack<Node<T>> stack, T data)
if(node == null)
return false;
stack.push(node);
if(node.data.equals(data))
return true;
Boolean found = getPath(node.left, stack, data) ||
getPath(node.right, stack, data);
if(!found )
stack.pop();
return found;
【讨论】:
以上是关于如何获取从根到二叉树上给定节点的路径?的主要内容,如果未能解决你的问题,请参考以下文章