Find child in non-binary tree (recursively) - java

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

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.

Calling a function with a getter as parameter doesn't retain refrence?

I am having an issue with my code, I am making a Binary Search Tree data structure, and when I call a function with a node's child, then assign a value to that child within the function, it doesn't update the node's child.
//*** Pseudo-ish Code ***
class BSTNode {
private BSTNode lChild;
private BSTNode rChild;
private int key;
public BSTNode(int key) {
this.lChild = null;
this.rChild = null;
this.key = key;
}
//getters and setters for each field ^
}
class BST {
private BSTNode root;
public BST() {
this.root = null;
}
public void insert(BSTNode currentNode, int value) {
BSTNode newNode = new BSTNode(value);
if (currentNode == null) {
currentNode = newNode;
if (this.root == null) {
this.root = currentNode;
}
} else {
//ignore the newNode == currentNode value statement right now
if (newNode.getValue() < currentNode.getValue()) {
insert(currentNode.getlChild(), value);
} else if (newNode.getValue() > curNode.getValue()) {
insert(curNode.getrChild(), value);
}
}
}
//getters and setters
}
I still want to figure out the code myself, but I am curious as to why if I were to run this code with:
BST testBST = new BST();
testBST.insert(testBST.getRoot(), 10);
testBST.insert(testBST.getRoot(), 7);
System.out.print(testBST.getRoot());
System.out.print(" ");
System.out.print(testBST.getRoot().getlChild());
This will output 10 then a NullPointerException. I understand this is because somehow the 7 didn't get allocated as 10's lChild, but I don't know why? Is it a scope issue I am having, or is it because I call recursively with the getlChild() in my insert function that I don't have access to the actual private lChild field?
NOTE: I was using sysout to debug my code, and I noticed the recursion does work, and it does assign the 7 properly to currentNode, but then once the function is done running, it is like currentNode no longer references the lChild of the initial root node.
The problem is here:
BSTNode newNode = new BSTNode(value);
Each time computer is calling the recursive method insert() , it is creating a new BSTNode(). You just want to add one new BSTNode() each time but it is creating nodes again and again. For example, You want to add 3 and for this it has to call insert() 4 times. Instead of creating only 1 node it will be creating 4 nodes.
What I have done, apart of removing some errors, I have created the recursive insertValue() method in BSTNode class. So you dont have to keep track of currentNode every time you call this method. As, every Node will be calling its own insertValue() method.
//*** Pseudo-ish Code ***
class BSTNode
{
public BSTNode lChild;
public BSTNode rChild;
public int key;
public BSTNode(int key)
{
this.lChild = null;
this.rChild = null;
this.key = key;
}
/* Create INSERT function in BSTNode class so that you dont have to give the "CurrentNode" everytime
you call this method, Now you just have to pass the "Key"*/
public void insertValue(int insertValue)
{
if(insertValue < key)
{
if(lChild == null)
lChild = new BSTNode(insertValue);
else
lChild.insertValue(insertValue);
}
else if(insertValue > key)
{
if(rChild == null)
rChild = new BSTNode(insertValue);
else
rChild.insertValue(insertValue);
}
else;
}
}
class BST
{
private BSTNode root;
public BST()
{
this.root = null;
}
// just create the root if not present else it'll call the recursive method of BSTNode class
public void insert(int value)
{
if(root == null)
root = new BSTNode(value);
else
root.insertValue(value);
}
// you didn't provide these methods so i wrote my own just to get your code runing
public BSTNode getRoot()
{
return root;
}
public int getRootValue()
{
return root.key;
}
}
public class BSTMain
{
public static void main(String[] args)
{
BST testBST = new BST();
testBST.insert(10);
testBST.insert(7);
System.out.print(testBST.getRootValue());
System.out.print(" ");
System.out.print(testBST.getRoot().lChild.key);
}
}
NOTE: I have added some methods like getRoot() just to get your code working, as you haven't provided them.

How do I get to node 25 and 50 in my binary tree? I have to get a preorder of the binary tree in output

//
// BinTree class
//
// this class implements a binary tree
//
// the tree is unbounded. fields are
// info: the value stored in the node (generic type)
// left: pointer to the left subtree
// right: pointer to the right subtree
// parent: pointer to the parent
// preOrderQueue: queue of nodes for preorder traversal
// left, right, and parent are public to allow the client // code to manipulate the tree as needed
//
// methods:
// constructor to create empty tree
// constructor to create tree with one node
// constructor to create tree given the root value, and
// pointers to the left and right subtrees
// get and set methods for the info field
// isEmpty
// attachLeft: if there is no left child, attach the given tree as
// the new left child; otherwisethrowTreeViolationException
// attachRight: if there is no right child, attach the given tree as the // new right child; otherwise throw TreeViolationException
// detachLeft: detach and return the left child
// detachRight: detach and return the right child
// root: return the root of the tree
public class BinTree<T> implements BinTreeInterface<T> {
protected T info;
public BinTree<T> left;
public BinTree<T> right;
public BinTree<T> parent;
private LinkedUnbndQueue<T> preOrderQueue;
// create an empty tree
public BinTree() {
info = null;
left = null;
right = null;
parent = null;
}
// create a tree with one node
public BinTree(T item) {
info = item;
right = null; //idk
left = null; //idk
}
// create a tree where the root contains item
// link the left and right subtrees to the root
// don't forget to set the parent pointers
public BinTree(T item, BinTree<T> ltree, BinTree<T> rtree) {
info = item;
right = rtree;
left = ltree;
ltree = null;
rtree = null;
}
// return the info field
public T getInfo() {
return info;
}
// set the info field
public void setInfo(T newitem) {
info = newitem;
}
// attach the parm as the left child of the current node
// throw TreeViolationException if the current node already has a left child
public void attachLeft(BinTree<T> tree) {
if (this.left != null)
throw new TreeViolationException("Current node already has a left child");
else
this.left = tree;
}
// attach the parm as the right child of the current node
// throw TreeViolationException if the current node already has a right child
public void attachRight(BinTree<T> tree) {
if (this.right != null)
throw new TreeViolationException("Current node already has a right child");
else
this.right = tree;
}
// detach the left child and return it
public BinTree<T> detachLeft() {
return this.left;
}
// detach the right child and return it
public BinTree<T> detachRight() {
return this.right;
}
I think my BinTree method is wrong. I dont understand where I am making mistake.
public BinTree<T> root() {
if (this.parent == null)
return this;
else
return this.root();
/// return parent;
}
// Initializes preOrderQueue with tree elements in preOrder order.
public void preOrder(BinTree<T> tree) {
if (tree != null) {
preOrderQueue.enqueue(tree.getInfo());
preOrder(tree.left);
preOrder(tree.right);
}
}
// calls preorder to create queue of nodes in the tree
public void reset() {
preOrderQueue = new LinkedUnbndQueue<T>();
preOrder(this);
}
// removes and returns the next node in the preorder queue
// returns null if the queue is empty
public T getNext() {
if (preOrderQueue.isEmpty())
return null;
else
return preOrderQueue.dequeue();
}
}
Here is my driver code.
// When I compile fr preorder it only prints out 75 and below bcz at tht time the current node is 75. why is it not traversing 25 and 50?
public class useTree {
public static void main(String[] args) {
Integer num;
BinTree<Integer> mytree = new BinTree<Integer>(25);
BinTree<Integer> subtree = new BinTree<Integer>(50);
mytree.attachLeft(subtree);
subtree = new BinTree<Integer>(75);
mytree.attachRight(subtree);
// subtree = new BinTree<Integer>(10);
// mytree.attachRight(subtree);
// 25
// / \
// 50 75
subtree = new BinTree<Integer>(10);
subtree.attachRight(new BinTree<Integer>(100));
subtree.attachLeft(new BinTree<Integer>(200));
mytree = mytree.right;
mytree.attachLeft(subtree);
// 25
// / \
// 50 75
// /
// 10
// / \
// 200 100
mytree = mytree.root();
System.out.println("\npreorder traversal:");
mytree.reset();
num = mytree.getNext();
while (num != null) {
System.out.println(num);
num = mytree.getNext();
}
}
}
public BinTree root() {
if (this.parent == null)
return this;
else
return this.root();
/// return parent;
}
Should be:
public BinTree root() {
if (this.parent == null)
return this;
else
return this.parent.root();
}
This uses recursion, which is less than optimal, but it is at least correct.
Also:
private LinkedUnbndQueue<T> preOrderQueue;
Each node of the tree has its own queue? That's not right. If you really want to generate a queue, pass the queue object to the relevant method. And, why does the preOrder method need a tree argument - it's not a static method; "this" serves as an implicit argument.
public void preOrder(LinkedUnbndQueue<T> preOrderQueue) {
preOrderQueue.enqueue(this.getInfo());
if (left != null) left.preOrder(preOrderQueue);
if (right != null) right.preOrder(preOrderQueue);
}
Also, attachLeft and attachRight methods needs to set the parent field of the attached subtree.
More generally, your BinTree is both a node and a tree. That can work but some operations don't really make sense on a per-node basis (in particular the custom iteration that you have defined should be moved out, since as I noted, it doesn't make much sense to have a queue per node).
Frankly, there are enough problems with this code that you need a better approach to your development practice. Consider learning to use a debugger.
public BinTree root() {
if (parent == null) return null;
BinTree tmp = parent;
while (tmp.parent != null) {
tmp = tmp.parent;
}
return tmp;
}
You should create a separate class naming BinNode or something. Tree and Node are separate things and the class you created is confusing and doesn't make sense.
Also, you are not assigning the parent variable anywhere.
public void attachRight(BinTree<T> tree) {
if (this.right != null)
throw new TreeViolationException("Current node already has a right child");
else {
this.right = tree;
tree.parent = this;
}
}
Assign the parent of the child branches appropriately. Moreover, your detach methods are wrong too. You are simply returning the right/left branches but you are supposed to detach/remove them first.
BinTree branch = this.right; // or left
this.right = null;
return branch;

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();
}

find object by id from nested object list in 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);
}
}

Categories

Resources