HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Recursive search to delete n'th child in tree

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
searchdeleterecursivechildtree

Problem

I have to implement a tree programming here. What I mean by tree programming is I have data stored in tree format. I have a parent object which will have child objects of same type the level of depth can go any long:

I am able to store objects in tree format and also able to display properly. I am facing problems when I have to filter some child nodes based on some conditions:

I have two question:

  • is this code fine?



  • is there anything wrong with design?



Plus, how can I handle removing child node in a tree where the child can be in any place?

```
package menu;
import java.util.List;
public class Links{
private String nodeName;
private List children;

public List getChildren(){
return children;
}

public void setChildren( List children ){
this.children = children;
}

public String getNodeName(){
return nodeName;
}

public void setNodeName( String nodeName ){
this.nodeName = nodeName;
}
}

package menu;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.chartis.gp.support.util.BrokerSupportUtil;
import com.chartis.gp.support.vo.Links;
import com.chartis.kernel.user.UserVO;
import com.chartis.kernel.utils.Utils;

public class Utility{

/* IN this class NavModel,CModel,CNode are some dummy classes
* which help us read contents form some resources which are stored in dummy format
* as Example of tree format stored data below is the example
* tree
* child1
* child2
* child3
* child3-1
* child:q
* child:r
* child:a
* child3-2
*
* child4
*/

private static void populateChildLinks(NavModel navModel, Object objectNode, Links parent ){
try{
List childLinks = new ArrayList();
Iterator it = navModel.get

Solution

It is not possible to test your classes, because of:

import com.chartis.gp.support.util.BrokerSupportUtil;
import com.chartis.gp.support.vo.Links;
import com.chartis.kernel.user.UserVO;
import com.chartis.kernel.utils.Utils;


But ok, the general idea is ( if we want to use recursion):

remove(child, tree):
    if tree.isLeaf: return false
    if tree.hasChild(child): tree.removeChild(child); return true;
    for all children of tree as subtree:
        if remove(child, subtree): return true;
    return false;


Methods you will most probably need:

public void addChild(Links child)
{
    children.add(child);
}

public boolean hasChild(Links child)
{
    return children.contains(child);
}

public boolean removeChild(Links child)
{
    return children.remove(child);
}

public boolean isLeaf()
{
    return children.size() <= 0;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((nodeName == null) ? 0 : nodeName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Links other = (Links) obj;
    if (nodeName == null) {
        if (other.nodeName != null)
            return false;
    }
    else if (!nodeName.equals(other.nodeName)) //hint: this only works if nodeName is unique! If not, use a unique static counter
        return false;
    return true;
}


Take a look at some of the tree-classes of java to see some typical methods.

And your method could look like:

public static boolean removeChildFromTree(Links child, Links tree)
{
    if (tree.isLeaf()) //we are at a leave, we can not delete any children anymore
        return false;
    if (tree.hasChild(child)) //we found it, quickly delete it
        return tree.removeChild(child);
    //we have to search all children
    for (Links subTree : tree.getChildren())
    {
        if (removeChildFromTree(child, subTree)) //try to delete on subtree
            return true;
    }
    return false;
}


Edit: Just to point out, this code is not for efficiency. It is written for clarity. Do not care about efficiency before you really have to.

Code Snippets

import com.chartis.gp.support.util.BrokerSupportUtil;
import com.chartis.gp.support.vo.Links;
import com.chartis.kernel.user.UserVO;
import com.chartis.kernel.utils.Utils;
remove(child, tree):
    if tree.isLeaf: return false
    if tree.hasChild(child): tree.removeChild(child); return true;
    for all children of tree as subtree:
        if remove(child, subtree): return true;
    return false;
public void addChild(Links child)
{
    children.add(child);
}

public boolean hasChild(Links child)
{
    return children.contains(child);
}

public boolean removeChild(Links child)
{
    return children.remove(child);
}

public boolean isLeaf()
{
    return children.size() <= 0;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((nodeName == null) ? 0 : nodeName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Links other = (Links) obj;
    if (nodeName == null) {
        if (other.nodeName != null)
            return false;
    }
    else if (!nodeName.equals(other.nodeName)) //hint: this only works if nodeName is unique! If not, use a unique static counter
        return false;
    return true;
}
public static boolean removeChildFromTree(Links child, Links tree)
{
    if (tree.isLeaf()) //we are at a leave, we can not delete any children anymore
        return false;
    if (tree.hasChild(child)) //we found it, quickly delete it
        return tree.removeChild(child);
    //we have to search all children
    for (Links subTree : tree.getChildren())
    {
        if (removeChildFromTree(child, subTree)) //try to delete on subtree
            return true;
    }
    return false;
}

Context

StackExchange Code Review Q#19455, answer score: 2

Revisions (0)

No revisions yet.