![](/img/trans.png)
[英]Finding the path from the root node to a specified node in a tree using recursion
[英]How to return an ArrayList of tree nodes spanning from the tree root to a target using recursion?
这个项目的目标是分析谁在金字塔计划中受益。 PyramidScheme.java 是一个数据结构,它扩展了LinkedTree(LinkedTree.java 是一个非常标准的树类),传入Person(一个Person.java 是金字塔计划的参与者,类信息无关紧要)对象代替泛型。
我无法弄清楚的有问题的方法是 findNodeChain。 这个方法是 PyramidScheme.java 的一个成员,应该返回一个 MultiTreeNode 的 ArrayList(MultiTreeNode.java 是一个非常标准的树节点类)对象,是从吸盘中“受益”的人 - 即上面的每个节点傻逼。 这是相关代码(findNodeChain 在底部):
/**
* Initiates the recursive findNodeChain method to return a list of all
* nodes that are above the node containing the target. This overload takes
* a Person.
*
* @param sucker the individual from whom others above are benefitting
* @return an ArrayList of individuals higher up in the hierarchy
*/
public ArrayList<MultiTreeNode<Person>>
whoBenefits(Person sucker) {
return findNodeChain(root, sucker);
}
/**
* Initiates the recursive findNodeChain method to return a list of all
* nodes that are above the node containing the target. This overload takes
* a MultiTreeNode.
*
* @param sucker the individual from whom others above are benefitting
* @return an ArrayList of individuals higher up in the hierarchy
*/
public ArrayList<MultiTreeNode<Person>>
whoBenefits(MultiTreeNode<Person> sucker) {
return findNodeChain(root, sucker.getElement());
}
/**
* Similar to findNode, but rather than returning the node that contains the
* target, instead returns a list of nodes above the one that contains the
* target, in low to high level order.
*
* @param node the current node being examined
* @param target the Person being searched for
* @return an ArrayList of nodes that are directly above the target in the
* hierarchy
*/
private ArrayList<MultiTreeNode<Person>>
findNodeChain(MultiTreeNode<Person> node, Person target) {
return findNodeChain(node, target, new ArrayList<>());
}
/**
* Primary helper method for findNodeChain
*
* @param node the current node being examined
* @param target the Person being searched for
* @param helper the ArrayList people to be returned
* @return an ArrayList of nodes that are directly above the target in the
* hierarchy
*/
private ArrayList<MultiTreeNode<Person>>
findNodeChain(MultiTreeNode<Person> node, Person target, ArrayList<MultiTreeNode<Person>> helper) {
if (node.getElement().equals(target)) {
// If this node is the target, add it to the list and return.
helper.add(node);
return helper;
} else {
//For each child of this node...
for (MultiTreeNode<Person> child : node.getChildren()) {
//...Call this method, seeing if the child can find our target.
helper.add(child);
helper = findNodeChain(child, target, helper);
//If it isn't null, then the child has found our target, and...
if (helper.get(helper.size() - 1) != null) {
return helper; //...The target is passed upwards.
}
}
// If none of the children have the target, return the passed ArrayList
return helper;
}
}
我开始尝试通过将 findNodeChain() 与 LinkedTree.java 中的 findNode() 方法分开来解决这个问题:
/**
* Finds the node that contains a target element. Calls the recursive
* overload to search for target.
*
* @param target the element being searched for
* @return the MultiTreeNode containing the target, or null if not found
*/
public MultiTreeNode<T> findNode(T target) {
if (target == null) {
return null;
}
return findNode(root, target);
}
/**
* Finds the node that contains a target element. This checks the current
* node, and if it is the target, returns it. Otherwise, it recursively
* checks each of the current node's children, to see if they can find it.
* If none of this node's children can find it either, then null is
* returned.
*
* @param node the node currently being examined
* @param target the element being searched for
* @return the MultiTreeNode containing the target, or null if not found
*/
private MultiTreeNode<T> findNode(MultiTreeNode<T> node, T target) {
//If this node is the one holding the target...
if (node.getElement().equals(target)) {
return node; //...Return this node, so it is passed upwards.
} else { //Otherwise...
MultiTreeNode<T> temp;
//For each child of this node...
for (MultiTreeNode<T> child : node.getChildren()) {
//...Call this method, seeing if the child can find our target.
temp = findNode(child, target);
//If it isn't null, then the child has found our target, and...
if (temp != null) {
return temp; //...The target is passed upwards.
}
}
//If none of the children found the target, return null.
return null; //This signifies that no target was found.
}
}
也试过这个:
/**
* Similar to findNode, but rather than returning the node that contains the
* target, instead returns a list of nodes above the one that contains the
* target, in low to high level order.
*
* @param node the current node being examined
* @param target the Person being searched for
* @return an ArrayList of nodes that are directly above the target in the
* hierarchy
*/
private ArrayList<MultiTreeNode<Person>>
findNodeChain(MultiTreeNode<Person> node, Person target) {
// Create the ArrayList here and pass its reference at each recursion
ArrayList<MultiTreeNode<Person>> helper = new ArrayList<>();
hasNodeChain(node, target, helper); // Pass the ArrayList
return helper; // Return the passed around ArrayList. Yay for pass by reference!!
}
/**
* Primary helper method for findNodeChain
*
* @param node the current node being examined
* @param target the Person being searched for
* @param helper the pointer of the ArrayList of people to be returned
* @return true if there is a path from node to target, false if not
*/
private boolean hasNodeChain(MultiTreeNode<Person> node, Person target, ArrayList<MultiTreeNode<Person>> helper) {
helper.add(node); // Assume this node is a member of the list.
if (node.getElement().equals(target)) { // If the node we're at equals the target, return it.
return true;
} else {
for (MultiTreeNode<Person> child : node.getChildren()) { // For each child in the node, recurse the method.
if (hasNodeChain(child, target, helper)) { // If a child has a path, this node is a member of the list.
return true;
}
}
// If none of the children are members, remove this node.
helper.remove(helper.size() - 1);
return false;
}
}
我想我已经接近解决这个问题了,但还没有完全解决。 我刚刚添加了树中的每个元素:(。有人可以提供一些指导吗?
我无法发表评论,所以我希望这对您有所帮助。
添加节点的条件是该节点是否在您要查找的节点的路径上。
所以如果我理解正确,你可以做这样的事情(只是不是像我所做的那样的简化例子):
private ArrayList<T> findNodeChain() {
if (findNode(node) != null) {
// If this node is the on the path to our node, add it to the list and return.
helper.add(node);
return helper;
} else {
// If none of the children have the target,
//there must not be a path or the node is at the end
return helper;
}
}
查看本教程以了解我要解释的内容。 我实际上写出了他们拥有的 C# 代码,我认为查看 Java 示例会对您有所帮助。
要获取MultiTreeNode
节点的祖先列表,您的递归调用需要将引用列表传递给自身,该列表不会由recursion where the target was found
的recursion where the target was found
初始化,而是由callee that triggered the recursion
的callee that triggered the recursion
初始化。 见下面的片段。
private boolean isParentOfTarget(MultiTreeNode<Person> suspect, Person target,
ArrayList<MultiTreeNode<Person>> chain) {
// Check whether the suspect is the target
if (suspect.getElement().equals(target)) {
// Suspect is actually the target :|
// No need to append to chain here!
return true; //just head home
}
else {
// Yet to find the target. So we check the children of the suspect
for (MultiTreeNode<Person> child : suspect.getChildren()) {
// The children may also have children
// Hence we do a recursive call
if(isParentOfTarget(child, target, chain)){
// Suspect is guilty :)
chain.add(suspect);
return true; //head home
}
// ...At this point
// Johnny is still lost... Continue Search!
}
return false; //Suspect not guilty :(
}
}
用法
ArrayList<MultiTreeNode<Person>> chain = new ArrayList<>();
Boolean is_pot = isParentOfTarget(root_node,target_person,chain);
if(is_pot){
// ... A relation exist between root_node and target_person
// Chain contains all parents of target_person excluding root_node
}
else{
// ... Root_node and target_person exists in two different worlds
// Chain is a blank slate
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.