'Building general trees in java (with recursion)
I have been stuck on a problem for quite a few days. My end goal is to perform preorder, inorder, and postorder traversals on a general tree. The problem I am having is just populating the tree. I am only able to add nodes to the root and to the root's children. I am not able to move "down" past the roots children. I woke up one morning with the idea of building the tree recursively from a bottom-up approach. I have never used recursion so first of all, is this possible? I would basically build the tree by creating the nodes at the bottom of the tree and then work my way up?
Here is my node class:
//Represents node of the Tree<T> class
public class Node<T>
{
public T data;
public List<Node<T>> children;
//Default constructor
public Node()
{
super();
children = new ArrayList<Node<T>>();
}
public Node(T data)
{
this();
setData(data);
}
//Return the children of Node<T>
public List<Node<T>> getChildren()
{
if(this.children == null)
{
return new ArrayList<Node<T>>();
}
return this.children;
}
//Sets the children of a Node<T> object
public void setChildren(List<Node<T>> children)
{
this.children = children;
}
//Returns the number of immediate children of this Node<T>
public int getNumberOfChildren()
{
if(children == null)
{
return 0;
}
return children.size();
}
//Adds a child to the list of children for this Node<T>
public void addChild(Node<T> child)
{
if(children == null)
{
children = new ArrayList<Node<T>>();
}
children.add(child);
}
public void addChildAt(int index, Node<T> child) throws IndexOutOfBoundsException
{
if(index == getNumberOfChildren())
{
addChild(child);
return;
}
else
{
children.get(index);
children.add(index, child);
}
}
public boolean isLeaf()
{
if(getNumberOfChildren() == 0)
return true;
return false;
}
public T getData()
{
return this.data;
}
public void setData(T data)
{
this.data = data;
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("{").append(getData().toString()).append(",[");
int i = 0;
for(Node<T> e : getChildren())
{
if(i > 0)
{
sb.append(",");
}
sb.append(e.getData().toString());
i++;
}
sb.append("]").append("}");
return sb.toString();
}
}
Here is my tree class:
//Tree class
public class Tree<T>
{
private Node<T> root;
//Default constructor
public Tree()
{
super();
}
//Returns the root
public Node<T> getRoot()
{
return this.root;
}
//Set the root of the tree
public void setRoot(Node<T> root)
{
this.root = root;
}
//Returns the Tree<T> as a List of Node<T> objects
public List<Node<T>> toList()
{
List<Node<T>> list = new ArrayList<Node<T>>();
walk(root, list);
return list;
}
//String representation of ttree
public String toString()
{
return toList().toString();
}
//Preorder traversal
private void walk(Node<T> element, List<Node<T>> list)
{
list.add(element);
for(Node<T> data : element.getChildren())
{
walk(data, list);
}
}
}
This is my main driver program:
//Importing packages
import java.util.Scanner;
import java.util.StringTokenizer;
import java.io.*;
import java.io.BufferedReader;
import java.util.List;
import java.util.ArrayList;
//Class header
public class treeTraversals
{
//Main method
public static void main (String[] args) throws IOException
{
//Defining variables
String file;
int size = 0;
int id = 1;
int counter = 1;
Scanner keyboard = new Scanner(System.in);
//Request file
System.out.print("Enter the filename: ");
file = keyboard.nextLine();
//Read file
File treeFile = new File(file);
Scanner inputFile = new Scanner(treeFile);
BufferedReader reader = new BufferedReader(new FileReader(file));
//Find size of input file
while(reader.readLine() != null)
{
size++;
}
reader.close();
String[] parent = new String[size+1];
String[] child = new String[size+1];
//Add file vaules to arrays
while(inputFile.hasNext())
{
String line = inputFile.nextLine();
StringTokenizer st = new StringTokenizer(line);
while(st.hasMoreTokens())
{
String previousValue = st.nextToken();
String nextValue = st.nextToken();
parent[counter] = previousValue;
child[counter] = nextValue;
counter++;
}
}
System.out.println();
//Output to the screen
System.out.println("The Tree");
System.out.println();
for(int l = 1; l <= size; l++)
{
System.out.print(parent[l] + " ");
System.out.println(child[l]);
}
//Create the root of the tree
Tree tree = new Tree();
Node root = new Node(parent[id]);
tree.setRoot(root);
Node active = new Node();
//Fill tree with nodes
for(id = 1; id <= size; id++)
{
Node parentNode = new Node(parent[id]);
Node childNode = new Node(child[id]);
active = root;
int passage = 0;
//Adds children to the root node
if(parentNode.getData().equals(active.getData()))
{
active.addChild(childNode);
System.out.println(tree.toList());
}
//Adds children to the root's children
else if(!parentNode.getData().equals(active.getData()))
{
boolean marked = false;
int i = -1;
int n = 0;
while(i != active.getNumberOfChildren() && marked == false && n <= 2)
{
active = root;
active = (Node)active.getChildren().get(n);
if(active.getData().equals(parentNode.getData()))
{
active.addChild(childNode);
marked = true;
}
i++;
n++;
}
active = root;
if(n >= 3 && marked == false)
{
for(int p=0; p < active.getNumberOfChildren(); p++)
{
active = (Node)active.getChildren().get(p);
if(active.getData().equals(parentNode.getData()))
{
active.addChild(childNode);
//p++;
marked = true;
}
else
{
active = root;
active = (Node)active.getChildren().get(p);
active = (Node)active.getChildren().get(p);
if(active.getData().equals(parentNode))
{
active.addChild(childNode);
System.out.println("No");
p = 0;
}
}
}
}
}
//See the nodes in the tree
System.out.println(tree.toList());
}
}
}
Lastly, here is the text file that is provided:
a b
a c
a d
b e
b f
d g
d h
d i
e j
e k
g l
g m
k n
k o
k p
Please, any help would be appreciated, I'm stuck on my own approach so I'm asking: how would I even start if I'm going with a recursive approach?
Solution 1:[1]
I have neglected the order for now, and just given an Tree.insert(parentData, data)
.
With the hope that this helps getting you started.
public class Node<T> {
private T data;
private List<Node<T>> children;
Node<T> find(T data) {
if (this.data.equals(data)) {
return this;
}
for (Node<T> node : children) {
Node<T> found = node.find(data);
if (found != null) {
return found;
}
}
return null; // Not found.
}
public class Tree<T> {
public find(T data) {
return root == null ? null : root.find(data);
}
public boolean insert(T parentData, T data) {
Node<T> found = find(parentData);
if (found == null) {
return false;
}
found.getChildren().add(new Node(data));
return true;
}
As one sees, having a find(data)
method for retrieving the (parent) Node helps.
The search method find
here disregards any sorting of the values, and does a preorder search.
As far as order is concerned, normally on has nodes of the form:
class Node<T> {
List<Node<T>> children; // 0, 1, ... N
List<T> values; // 0, 1, ... N-1
}
With an sort ordering:
children[0]
values[0}
children[1}
values[0]
children[2]
...
children[N-1]
values[N-1]
children[N]
One might retain the values in the entire tree in this order. Sorting and preorder/postorder walks and bread fĂrst/depth first walks are different notions.
Solution 2:[2]
import java.util.*;
public class GeneralTree {
class Node {
int value;
ArrayList<Node> list;
public Node(int value, ArrayList<Node> list) {
this.value = value;
this.list = list;
}
}
public void traverse(Node node) {
System.out.print(node.value + " ");
for (int i = 0; i < node.list.size(); i++) {
traverse(node.list.get(i));
}
}
public static void main(String[] args) {
GeneralTree tree = new GeneralTree();
GeneralTree.Node node5 = tree.new Node(5, new ArrayList(Arrays.asList()));
GeneralTree.Node node6 = tree.new Node(3, new ArrayList(Arrays.asList()));
GeneralTree.Node node1 = tree.new Node(1, new ArrayList(Arrays.asList(node5, node6)));
GeneralTree.Node node3 = tree.new Node(99, new ArrayList(Arrays.asList(node6)));
GeneralTree.Node node2 = tree.new Node(45, new ArrayList(Arrays.asList(node1, node3)));
tree.traverse(node2);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Joop Eggen |
Solution 2 | Nisab Mohd |