![](/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.