find object by id from nested object list in java - java

I have a java bean class :
class Node{
int id, parentId;
String value;
List<Node> childs;
}
How could i find a parent node in this hierarchy and insert a child node in the child list of parent node.
relationship between to node is defined as :
if node1.id == node2.parentid then node2 will be in child list of node1.
This can be Nth level hierarchy.

In order to find a node in that hierarchy, you'll have to implement a method for traversing. I suggest using a recursive method and employ either a breadth-first or depth-first search pattern. Once you've located the correct Node, insert the child.
For instance:
public Node search(Node root, int searchId) {
if (root.id == searchId) {
return root;
} else {
for (Node child : root.childs) {
Node node = search(child, searchId);
if (node != null) {
return node;
}
}
}
return null;
}
public void insert(Node node) {
Node parent = search(root, node.parentId);
if (node != null) {
parent.childs.add(node);
}
}

Try something like this
insertNode(Node nodeToInsert, Node anyNodeInHirarchy) {
Node parent = getParentNodeById(anyNodeInHirarchy.parentId);
if(parent.Id == nodeToInsert.parentId) {
parent.childs.add(nodeToInsert);
} else {
insertNode(nodeToInsert, parent)
}
}
return getParentNodeById(int nodeId) {
// Find node by id and return
return node;
}

easily :
childNode.setParentId(parentNode.getId());
parentNode.getChilds().add(childNode);

Fast way of doing it is
Guid should point the object easily so that you can point nth node easily.
Generate a Single Random GUID
for eg : say 45892
Root node will point to that id.
child will point in the pattern Parent_ID+"-"+Index_Number
If consider three child will have 45892-0, 45892-1, 45892-2
And child of first node becomes - 45892-0-1, 45892-0-2
So you can travel directly using the id as faster and need not search, search time will be saved.
If you don't understand please comment. I will show in programming.
Note : ID length grows as depends on your level of usage.
If you have data already in the db or some persistent store.then you can prefer jgitter code. if not you can prefer this.
class Node {
public String id;
public String parentId;
public List<Node> childs;
}
class Operation {
public Node getChildNodeByID(Node root,String parentId) {
String[] keys = parentId.split("-");
Node parentNode = root;
int index = 0;
for(String key : keys ) {
if(index == 0) {
if( !root.id.equals(key) ) {
throw new IllegalArgumentException("Root node does not match so parent node will not be found in this node");
}
}else {
int myIndex = Integer.parseInt(key);
if( parentNode.childs.getSize() > myIndex ) {
parentNode = parentNode.childs.get(myIndex);
}else {
throw new IllegalArgumentException("Parent Node does not exist");
}
}
index++;
}
return parentNode;
}
public insert(Node node,Node root) {
Node parentNode = getChildNodeByID(root,node.parentId);
node.id = node.parentId+"-"+parentNode.childs.getSize();
parentNode.childs.add(node);
}
}

Related

Tree-Structure does not inherit generics

My goal is to create a tree-like object structure.
For this i created a class named Node (I removed the implementation because the problem still persists without it):
public class Node<S> {
public Node<S> addChild(Node<S> node) {
return this;
}
}
Important to know is that i want to define the generic type S only in the root node, all child nodes should automatically inherit from the root node.
Something like this:
new Node<String>().addChild(
new Node<>().addChild(
new Node<>()
)
)
I restricted the addChild method to only accept Nodes with the same generic type S,
so as far as i know my child node should know that it's generic type S has to be (in this example) String. However it seems like the generic type S gets lost after instantiating a new Node, because it gives me the following Exception:
error: incompatible types: Node<Object> cannot be converted to Node<String>
The use of <> requires type inference, and the argument of the first
addChild must be a Node, and just passing new Node<>() would do - infering from the return type.
But chaining to .addChild(new Node<>()) cannot infer anything, can only provide Node<Object>. So: one cannot use <>.
The problem is (of course) that you want addChild to return the head of the list, and keep adding to the tail of the list.
Normal practice is not to create Node instances, but just use the S values.
public class Node<S> {
private S value;
private Node<S> next;
public Node(S value) {
this.value = value;
}
public static <T> void print(Node<T> root) {
if (root == null) {
System.out.println("empty");
return;
}
System.out.print(root.value);
System.out.print(" --> ");
print(root.next);
}
public static <T> Node<T> addAll(T... values) {
Node<T> root = null;
Node<T> previous = null;
for (T value : values) {
Node<T> current = new Node<>(value);
if (root == null) {
root = current;
} else {
previous.next = current;
}
previous = current;
}
return root;
}
public static void main(String[] args) {
Node<String> root = Node.addAll("a", "b", "c", "d");
print(root);
}
}
Comparable to Collections.addAll or List.of. If you keep a Node<S> last field, you could indeed create something like:
public void addLast(S value) {
last.next = new Node<>(value);
}
This also shows a serious problem of the class: an empty list is not a Node.
One could use Optional<Node<S>> or a special constant for an empty list EMPTY - without value.
The normal solution is to have a container:
public class List<S> {
private class Node {
...
}
private Node<S> root;
private Node<S> last;
private int size;
public List<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return this;
}
private int size() {
return size;
}
...
}
Now everything fits.
List<String> nodes = new List<>()
.addLast("a")
.addLast("b")
.addLast("c")
.addLast("d");
After feedback, when wanting Node references.
Then discard chaining, and make Node public again.
public Node<S> addLast() {
addLast(null);
}
public Node<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return last;
}
List<String> nodes = new List<>()
Node<String> a = nodes.addLast();
Node<String> b = nodes.addLast();
var c = nodes.addLast();
var d = nodes.addLast();
One could use var for shortness.
What you are trying to do is something like this
public class Node<T> {
private Node<T> child;
private T data = null;
public Node (T data) {
this.data = data;
}
public T getData() {
return data;
}
public Node<T> getChild() {
return child;
}
public void addChild(Node<T> child) {
this.child = child;
}
#Override
public String toString() {
return "this node's data: " + data + "; has child? " + (child != null);
}
public static void main(String[] args) {
Node<String> root = new Node<> ("parent");
Node<String> child = new Node<>("child");
root.addChild(child);
System.out.println(root);
System.out.println(child);
}
}
If you were to execute this, it will output
this node's data: parent; has child? true
this node's data: child; has child? false
this node's data: 0; has child? false
this node's data: 1; has child? false
Notice how I can create nodes of type String and Integer. However, this class is incomplete if you want to create a tree structure. The implementation of "tree" will depend on what kind of tree you are talking about. For example, a simple binary tree will have two children at most. Other types of trees could have more children. Also, adding nodes to a tree might require balancing the tree.
Now, to your question, this answer suffices. I was able to demonstrate the use of generics to create Node objects of type T.

Mirror a binary tree

I have a simple Node class to construct a tree node in my binary tree:
class Node {
int data;
Node left;
Node right;
public Node(int i) {
this.data = i;
}
}
I've written a simple Tree class which will use the Node structure to build a tree:
class Tree {
Node root;
}
I'm trying to write a recursive function mirror() in my Tree class that will return a mirrored version of the tree (left and right nodes swapped).
So if I call this function on a Tree t, I would expect to start from the root, and swap all of the nodes until we reach a node that has no more children to swap. The part I'm struggling with is after we've swapped the root nodes children, how I can recursively call the mirror function on these nodes and then return the mirrored tree.
As you can see, the code below will swap the root node's children, but after that I am stuck as I can't call the mirror function on nodes, only a tree.
public Tree mirror() {
Node temp = this.root.left;
this.root.left = this.root.right;
this.root.right = temp;
If you could point me in the right direction I'd appreciate it.
You need a separate method that will accept Node object, mirror its children and call itself recursively.
public Tree mirror() {
mirrorInternal(this.root);
return this;
}
private void mirrorInternal(Node node) {
Node tmp = node.left;
node.left = node.right;
node.right = tmp;
if (node.left != null) {
mirrorInternal(node.left);
}
if (node.right != null) {
mirrorInternal(node.right);
}
}
I guess you could also change your Node-class such that it uses a flag for mirrored behavior:
class Node {
int data;
Node[] children;
public Node(int i) {
this.data = i;
this.children = new Node[2];
}
public void setLeft(Node node) {
children[0] = node;
}
public void setRight(Node node) {
children[1] = node;
}
public Node getLeft(boolean mirrored) {
return mirrored ? children[1] : children[0];
}
public Node getRight(boolean mirrored) {
return mirrored ? children[0] : children[1];
}
}
void mirror (Tree tree) {
mirror (tree.root);
}
Node mirror (Node node) {
if (node != null) {
Node temp = node.left;
node.left = mirror (node.right);
node.right = mirror (temp);
}
return node;
}

Find child in non-binary tree (recursively)

I have TreeNode class - implementation of the node of the non-binary tree (List<TreeNode> children).
I need find the first node with the given data among the children of this. I wrote some method, but there is some problem obviously (java.lang.AssertionError: Failed to find a child with not-null data: expected:<2> but was:<null>). (if data is null I need to return first child with null data).
public TreeNode findChild(Object data) {
if (data == null) {
Iterator<TreeNode> a = getChildrenIterator();
TreeNode tmp;
while (a.hasNext()) {
tmp = a.next();
if (tmp.getData()==null) return tmp;
tmp.findChild(data);
}
}else
{
Iterator<TreeNode> a = getChildrenIterator();
TreeNode tmp;
while (a.hasNext()) {
tmp = a.next();
if (data.equals(tmp.getData())) return tmp;
tmp.findChild(data);
}
}
return null;
}
Your recursion isn't correct. You should be returning the result of tmp.findChild() if it returns a non-null value.
You also need to consider whether you're supposed to be implementing a depth-first or breadth-first search.
The problem is within the fact you don't return the result of the recursive call.
Maybe the following code will help:
import java.util.*;
public class TreeNode
{
// Constructor
public TreeNode()
{
children = new ArrayList<TreeNode>();
node_data = null;
}
// Get node's data
public Object getData()
{
return (node_data);
}
// Set node's data
public void setData(Object data)
{
node_data = data;
}
// Find the node with specified data
// Return null if not found
public TreeNode findChild(Object data)
{
// Maybe we're the one we're looking for
if (equalData(data))
return (this);
// Search within child nodes
Iterator<TreeNode> it;
TreeNode node;
it = getChildrenIterator();
while (it.hasNext())
{
node = findChild(it.next());
if (node != null)
return (node);
}
// If we get here, we didn't find it
return (null);
} // findChild
// Return whether specified data equals ours
private boolean equalData(Object data)
{
if (node_data == null)
return (data == null);
else
return (node_data.equals(data));
}
// Return iterator over node's children
private Iterator<TreeNode> getChildrenIterator()
{
return (children.iterator());
}
// The node's children
private List<TreeNode> children;
// The node's data
private Object node_data;
} // class TreeNode

How can I get all leaf nodes of a tree?

Suppose I have a node in a tree, how can I get all leaf nodes whose ancestor is this node?
I have defined the TreeNode like this:
public class TreeNode<T>
{
/** all children of the node */
private List<TreeNode<T>> children = new ArrayList<TreeNode<T>>();
/** the parent of the node, if the node is root, parent = null */
private TreeNode<T> parent = null;
/** the stored data of the node */
private T data = null;
/** the method I want to implement */
public Set<TreeNode<T>> getAllLeafNodes()
{
Set<TreeNode<T>> leafNodes = new HashSet<TreeNode<T>>();
return leafNodes;
}
}
Use recursion.
if the node itself is a leaf, return it
otherwise, return all the leaf-nodes of its children
Something like this (not tested):
public Set<TreeNode<T>> getAllLeafNodes() {
Set<TreeNode<T>> leafNodes = new HashSet<TreeNode<T>>();
if (this.children.isEmpty()) {
leafNodes.add(this);
} else {
for (TreeNode<T> child : this.children) {
leafNodes.addAll(child.getAllLeafNodes());
}
}
return leafNodes;
}
Create a stack and push root node.
Stack<Node> st = new Stack<>();
st.push(root);
CL(st.peek());
Call the recursive method.
public void CL(Node root){
if (st.peek().left == null && st.peek().right == null ) {//if leaf node
System.out.println(st.peek().data);//print
st.pop();
return;
}
else{
if(st.peek().left != null){
st.add(st.peek().left);
CL(st.peek());
}
if(st.peek().right != null){
st.add(st.peek().right);
CL(st.peek());
}
}
st.pop();
}

Searching through a BST

I created a BST that sets each node to a String value, I was wondering if there is a way to search through the tree but just one value at a time. So say the String in a node was "truck" is there a way to search through the tree and return "t"? This is the code I have for building the tree:
public class BinaryTree {
public Node root;
public BinaryTree tree;
public static int pos;
public static Node[] theArray;
private static class Node {
Node left;
Node right;
String data;
Node(String s) {
left = null;
right = null;
data = s;
}
}
public BinaryTree plantTree(ArrayList<String> dict) {
tree = new BinaryTree();
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
tree.add(s);
}
return tree;
}
/**
* Creates an empty binary tree
*/
public BinaryTree() {
root = null;
}
public void add(String data) {
root = add(root, data);
}
private Node add(Node node, String data) {
if (node == null) {
node = new Node(data);
} else {
if (data.compareTo(node.data) > 0) {
node.left = add(node.left, data);
} else {
node.right = add(node.right, data);
}
}
return (node);
}
}
Maybe I misunderstood your question, but it sounds like you want something to iterate through the tree. I would use the visitor pattern. (This sounds like homework anyways, so why not use standard patterns. :))
public class Node<T>{
...
public void visitDepthFirst(Visitor<T> v){
v.visit(this);
if (left != null){
left.visitDepthFirst(v);
}
if (right != null){
right.visitDepthFirst(v);
}
}
}
interface Visitor<T>{
public void visit(T t);
}
...
Node<String> root = ...;
root.visitDepthFirst(new Visitor<String>(){
public visit(String val){
if ("truck".equals(val)){
// do something
}
}
});
I'll let you figure out breadth search. Also, your node class would be more usable using generics. And your class structure is a bit confusing. Might I suggest you just use node AS the tree itself. After all, every node in a tree, is a tree itself. (read about the composite pattern)
So it appears that your trying to search through your tree by the first letter only. This will take just as long as returning the entire word. So you still have to use a BST traversal or search algorithem.
So say the String in a node was "truck" is there a way to search
through the tree and return "t"?
Really, I have no idea what this question is about.
If you have a BST then you search it using binary search. That's that.
A binary search returns true if the element is found. You can implement your own BST and not return a boolean but a Char as in t in your question and null if the value is not part of the tree.

Categories

Resources