In this binary tree implementation
I've tried to create an object from the BinaryTree class and thus insert elements and access them in order. While debugging it seems it's always returning root as NULL and thus the traversal fails.
I don't understand what I'm missing here. Where is my mistake?
public class BinaryTree{
public static class Node{
int value;
Node left;
Node right;
public Node(int data){
this.value = data;
left = null;
right = null;
}
}
Node root;
BinaryTree() {
root = null;
}
public Node addrecursive(Node current,int value){
if(current==null){
return new Node(value);
}else
if(value<current.value){
int n=current.value;
current.left=addrecursive(current.left,value);
}else
if(value>current.value){
int n=current.value;
current.right=addrecursive(current.right,value);
}else
{
return current;
}
return current;
}
public void add(int value) {
Node n = null;
if(root==null)
root = addrecursive(root, value);
else
n = addrecursive(n, value);
}
private void createBinaryTree(){
BinaryTree bt = new BinaryTree();
bt.add(6);
bt.add(4);
bt.add(8);
bt.add(3);
bt.add(5);
bt.add(7);
bt.add(9);
return;
}
private boolean containsNodeRecursive(Node current, int value) {
if (current == null) {
return false;
}
if (value == current.value) {
return true;
}
return value < current.value
? containsNodeRecursive(current.left, value)
: containsNodeRecursive(current.right, value);
}
public boolean containsNode(int value) {
return containsNodeRecursive(this.root, value);
}
public void traverseInOrder(Node node) {
if (node != null) {
traverseInOrder(node.left);
System.out.print(" " + node.value);
traverseInOrder(node.right);
}
}
void printInorder() { //wrapper class for access without passing node
traverseInOrder(root);
}
public static void main(String [] args){
BinaryTree bt = new BinaryTree() ; //object of class
bt.createBinaryTree(); //creating the binary tree within that object
Boolean b = bt.containsNode(7);
System.out.println(b);
System.out.println("\nInorder traversal of binary tree is " );
bt.printInorder();
}
}
There are several issues:
In addrecursive the variable n is a local reference that is unrelated to your root. So whatever n = addrecursive(n, value); does with the null that you pass as argument, it doesn't do anything with the linked list that starts at root.
It is actually quite simple... Your addrecursive function should only do:
public void add(int value) {
root = addrecursive(root, value);
}
The assignment to root is only really needed when root was null, but it doesn't hurt to always make that assignment. It is however important to pass root as argument, as that is the lead for where to append the new node.
createBinaryTree creates a new local instance of BinaryTree (which is already strange, since this already is an instance), adds nodes to it, and then just discards that local instance -- all work done for nothing. There are different ways to solves this, but I would make this method a static method, and have it return the BinaryTree instance that it populated. The caller in main should then take that returned tree and assign it to its own variable:
// Static!
private static BinaryTree createBinaryTree(){
BinaryTree bt = new BinaryTree();
bt.add(6);
bt.add(4);
bt.add(8);
bt.add(3);
bt.add(5);
bt.add(7);
bt.add(9);
return bt; // return the work that was done
}
public static void main(String [] args){
// Call static function to get the reference to the new tree
BinaryTree bt = createBinaryTree();
Boolean b = bt.containsNode(7);
System.out.println(b);
System.out.println("\nInorder traversal of binary tree is " );
bt.printInorder();
}
Related
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.
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.
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
This is the initial class provided which we cannot modify
public class SLL {
public class Node {
private int data;
private Node next;
public Node() {
data = 0;
next = null;
}
public Node(int newData, Node linkValue) {
data = newData;
next = linkValue;
}
public int getData() {
return data;
}
public Node getLink() {
return next;
}
}// End of Node inner class
private Node head;
public SLL() {
head = null;
}
public void addToStart(int itemData) {
head = new Node(itemData, head);
}
public boolean contains(int item) {
return (find(item) != null);
}
/**
* Finds the first node containing the target item, and returns a reference
* to that node. If target is not in the list, null is returned.
*/
public Node find(int target) {
Node position = head;
int itemAtPosition;
while (position != null) {
itemAtPosition = position.data;
if (itemAtPosition == target) {
return position;
}
position = position.next;
}
return null; // target was not found
}
public void outputList() {
Node position = head;
while (position != null) {
System.out.print(position.data + " ");
position = position.next;
}
System.out.println();
}
}
And this is the Set class that we are supposed to finish to get the Tester to work and I keep getting a Null Pointer Exception with my add method, however, it is almost exactly as I have seen in other codes including our text book. Any insight would be very much appreciated as my instructor has pre-made powerpoints and doesn't explain anything or offer any advice to students seeking help.
public class Set {
private SLL[] hashArray; // DO NOT MODIFY THIS LINE
private int size = 10; // DO NOT MODIFY THIS LINE
// DO NOT MODIFY THIS METHOD
public Set() {
hashArray = new SLL[size];
}
// DO NOT MODIFY THIS METHOD
private int computeHash(int s) {
return s % size;
}
// COMPLETE BELOW
public void add(int x)
{
int hash = computeHash(x); // Get hash value
SLL list = hashArray[hash];
if (!list.contains(x))
{
// Only add the target if it's not already
// on the list.
list.addToStart(x);/*replaced hashArray[hash] with list*/
}
}
public void output( )
{
System.out.println("I will work on this later");
}
}
Finally, the Tester...
public class Tester{
// Have this method to display your name, instead.
static void displayName(){
System.out.println("Program written by Tony.\n");
}
// DO NOT MODIFY THE MAIN METHOD
public static void main(String[] args){
displayName();
Set set1 = new Set();
Set set2 = new Set();
set1.add(3);
set1.add(3);
set1.add(13);
set1.add(23);
set1.add(4);
set1.add(5);
set2.add(15);
set2.add(6);
set2.add(6);
System.out.println("Contents of set 'set1': ");
set1.output();
System.out.println("Contents of set 'set2': ");
set2.output();
System.out.println();
}
}
I don't want to give the answer directly as this is likely a homework assignment (correct me if I am wrong). Consider the very first time the add method is called on a newly constructed set. What values are in all indices of "hashArray" at this time and what does that mean for the local variable "list" in your add method?
This line isn't doing what you think it's doing.
hashArray = new SLL[size];
You need to actually create each SLL that will populate the array once the array itself is created.
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.