views:

174

answers:

4

Hi all ,

I have recently faced this question in a practical test for a job .

Suppose you are given a flat data structure like this :

**Category**         **Name**         **Parent**
1                   electronics          0
2                   Television           1
3                    21inch              2
4                    23inch              2
5                   LCD display          2
6                   player               1
7                   mp3player            6
8                   vcd player           6
9                   dvd player           6
10                  hd quality           8

Now from the above flat data structure we want to show something like the below hierarchical tree structure .

 -Electronics
|   -Television
|   |   -21 inch
|   |   -23 inch
|   |   -lcd display
|   -Player
|   |   -mp3player
|   |   -vcdplayer
|   |   | -HD display
|   |   -DVD player

Then If I am adding another entry to my array like :

11                 Test               3

then it should show Test entry just below 21inch .

So for this sort of thing I am currently using ArrayList and have been able to traverse till second level but can't do so for third level . So what is the perfect way for doing this ?

Thanks

EDIT :

I was asked to build this concept using DOS based java application only.

+2  A: 

You could have a design inspired by Swing TreeModel.

EDIT When I say that, I mean you could use a class implementing a likewise interface; Noticeyou can even go as far as using directly this interface, as Swing is a part of standard JRE and is available everywhere standard Java is avaiable.

Furthermore, as it is an interface (and not a class), it's only a way for you to structure your calls. As a consequence, you can easily use it in a console based application.

Riduidel
Please see the question edit
hib
+1  A: 

Using your ArrayList as input a recursive method will be needed to print all nodes in a hierarchical/tree representation.

If you are not using recursion then this might be the reason that you cannot go to levels greater than the second one, that you mention.

Some links on recursion:

http://en.wikipedia.org/wiki/Recursion

http://www.java-samples.com/showtutorial.php?tutorialid=151

andreas
It would be nice if you can put some code snippet so I can understand yours one as I am confused with mine one
hib
+3  A: 

Here is some sample code that lists them in a hierarchy using recursion. The Item class has a List of children. The trick is adding any new children to the right parent. Here is the method I created to do this:

public Item getItemWithParent(int parentID){
    Item result = null;
    if(this.categoryID == parentID){
        result = this;
    } else {
        for(Item nextChild : children){
            result = nextChild.getItemWithParent(parentID);
            if(result != null){
                break;
            }
        }
    }
    return result;
}

There is probably a more efficient way, but this works.

Then, when you want to add new items to your hierarchy, do something like this:

public void addItem(int categoryID, String name, int parentID) {
    Item parentItem = findParent(parentID);
    parentItem.addChild(new Item(categoryID, name, parentID));
}
private Item findParent(int parentID) {
    return rootNode.getItemWithParent(parentID);
}

For the actual display, I just pass in a "tab level" that says how far to tab in, then increment it for each child like this:

public String toStringHierarchy(int tabLevel){
    StringBuilder builder = new StringBuilder();
    for(int i = 0; i < tabLevel; i++){
        builder.append("\t");
    }
    builder.append("-" + name);
    builder.append("\n");
    for(Item nextChild : children){
        builder.append(nextChild.toStringHierarchy(tabLevel + 1));
    }
    return builder.toString();
}

Which gives me this:

-electronics
    -Television
        -21inch
            -Test
        -23inch
        -LCD display
    -player
        -mp3player
        -vcd player
            -hd quality
        -dvd player
Matt N
Would've gone the same way. Converting into an object tree has many advantages, such as being able to sort the list of children of each of the nodes.I would maintain a HashMap in order to look up specific nodes, since recursive tree searches (like your getItemWithParent() ) are somewhat expensive.
f1sh
Good point. Using an actual Tree would be more efficient, though I thought it might be more complicated than needed for this example.
Matt N
+1  A: 

To be efficient, I'd create something like this:

public class Node
{
  // My name
  public String name;
  // My first child. Null if no children.
  public Node child;
  // The next child after me under the same parent.
  public Node sibling;

  // The top node in the tree.
  public static Node adam;

  // Add first node to tree
  public Node(String name)
  {
    this.name=name;
    this.child=null;
    this.sibling=null;
    adam=this;
  }

  // Add a non-Adam node to the tree.
  public Node(String name, Node parent)
  {
    // Copy my name. Easy part.
    this.name=name;
    // Make me the first child of my parent. The previous first child becomes
    // my sibling. If the previous first child was null, fine, now my sibling is null.
    // Note this means that children always add to the front. If this is undesirable,
    // we could make this section a little more complicated to impose the desired
    // order.
    this.sibling=parent.child;
    parent.child=this;
    // As a new node, I have no children.
    this.child=null;
  }
  // Print the current node and all nodes below it.
  void printFamily(int level)
  {
    // You might want a fancier print function than this, like indenting or
    // whatever, but I'm just trying to illustrate the principle.
    System.out.println(level+" "+name);
    // First process children, then process siblings.
    if (child!=null)
      child.printFamiliy(level+1);
    if (sibling!=null)
      sibling.printFamily(level);
  }
  // Print all nodes starting with adam
  static void printFamily()
  {
    adam.printFamily(1);
  }
  // Find a node with a given name. Must traverse the tree.
  public static Node findByName(String name)
  {
    return adam.findByName(name);
  }
  private Node findByNameFromHere(String name)
  {
    if (this.name.equals(name))
      return this;
    if (child!=null)
    {
      Node found=child.findByNameFromHere(name);
      if (found!=null)
        return found;
    }
    if (sibling!=null)
    {
      Node found=sibling.findByNameFromHere(name);
      if (found!=null)
        return found;
    }
    return null;
  }
  // Now we can add by name
  public Node(String name, String parentName)
  {
    super(name, findByName(parentName));
  }
}

Usual disclaimer: This code is off the top of my head, completely untested.

If I was doing this for a real application, I would include error checking and no doubt all sorts of peripheral stuff.

Jay
Storing the next sibling instead of a list of children... I cannot get used to this!
f1sh
Storing the next sibling makes it a linked list, which then conveniently makes the data structure fixed. If you store a list of children, then you have to have a dynamically sized array attached to each node. In another sense, storing the next sibling is a list of children: as a linked list. We just happen to let the node itself double as the list entry.
Jay