How to find a value in a binary tree - java

I have a binary tree like the picture below, I want to implement a method called findNode to return the node holding the value entered as a parameter.
For example: findNode(8)=8, findNode(13)=13.
I tried to modify this code but it didn't working :
class Node {
Node left, right;
int value;
public Node findNode(int value) {
Node focusNode = root;
if (focusNode == null) {
return null;
}
while (focusNode.value != value) {
// If we should search to the left
if (value < focusNode.value) {
// Shift the focus Node to the left child
focusNode = focusNode.left;
} else {
// Shift the focus Node to the right child
focusNode = focusNode.right;
}
return focusNode;
}
}
}

See if this helps. You can't default to left or right but need to check them explicitly. The null situation is taken care of by the while loop.
public Node findNode(int value) {
Node focusNode = root;
while (focusNode != null) {
// If we should search to the left
if (value < focusNode.value) {
// Shift the focus Node to the left child
focusNode = focusNode.left;
} else if (value > focusNode.value) {
// Shift the focus Node to the right child
focusNode = focusNode.right;
} else {
// Found!!
return focusNode;
}
}
return null;
}

Here's a cleaner approach:
class Node {
Node left, right;
int value;
public static Node findNode(Node current, int value) {
if (current == null)
return null;
if (current.value == value)
return current;
if (current.value < value)
return findNode(current.left, value);
else
return findNode(current.right, value);
}
}

your root is either not defined or null every time.
below code would work as expected.
class Node
{
int value;
Node left, right;
public Node(int item)
{
value = item;
left = right = null;
}
}
public class BinaryTree {
Node root;
public Node findNode(int value) {
Node focusNode = root;
if (focusNode == null){
return null;
}
while (focusNode.value!= value) {
// If we should search to the left
if (value< focusNode.value) {
// Shift the focus Node to the left child
focusNode = focusNode.left;
} else {
// Shift the focus Node to the right child
focusNode = focusNode.right;
}
}
return focusNode;
}

Related

Java - Return the node visited after node x in a pre-order traversal of BT

I am being asked to "Return the node visited after node x in a pre-order traversal of a binary tree" in Java for school. I have created a code to list all the nodes in pre-order, but I'm not sure how to print off a single node.
My first class to create the nodes is:
public class TreeNode {
int value; // The data in this node.
TreeNode left; // Pointer to the left subtree.
TreeNode right; // Pointer to the right subtree.
TreeNode parent; //Pointer to the parent of the node.
TreeNode(int value) {
this.value = value;
this.right = null;
this.left = null;
this.parent = null;
}
public void displayNode() { //Displays the value of the node.
System.out.println(value + " ");
}
I then have the class to build the binary tree. It also prints the whole tree in pre-order:
public class BTree2 {
TreeNode root; // the first node in the tree
public boolean isEmpty() // true if no links
{
return root == null;
}
private TreeNode addRecursive(TreeNode current, int value) {
if (current == null) {
return new TreeNode(value);
}
if (value < current.value) {
current.left = addRecursive(current.left, value);
} else if (value > current.value) {
current.right = addRecursive(current.right, value);
} else {
// value already exists
return current;
}
return current;
}
public void add(int value) {
root = addRecursive(root, value);
}
void printPreorder(TreeNode node) {
if (node == null) {
return;
}
System.out.print(node.value + " "); /* first print data of node */
printPreorder(node.left); /* then recur on left subtree */
printPreorder(node.right); /* now recur on right subtree */
}
void printPreorder() {
printPreorder(root);
}
This is where I get stuck: how do I print off the node that comes after a particular node, and not just the whole tree? I thought it would be:
public TreeNode findPreorder(int key) // find node with given key
{ // (assumes non-empty tree)
TreeNode current = root; // start at root
while (current.value == key) // while there is a match
{
current = current.left;
if (key < current.value) // go left?
{
current = current.right;
} else {
current = current.right; // or go right?
}
if (current == null) // if no child,
{
return null; // didn't find it
}
}
return current; // found it
}
But that's not working. This is my test code in my main:
public static void main(String[] args) {
BTree2 tree = new BTree2();
tree.root = new TreeNode(1);
tree.root.left = new TreeNode(2);
tree.root.right = new TreeNode(3);
tree.root.left.left = new TreeNode(4);
tree.root.left.right = new TreeNode(5);
System.out.println("Preorder traversal of binary tree is ");
tree.printPreorder();
System.out.println("the node after 1 is " + tree.findPreorder(1).value);
}
My output is:
Preorder traversal of binary tree is
1 2 4 5 3
the node after 1 is 5
Any ideas? Thanks!!
You can basically use the same function for visiting in pre order manner with some modifications:
void findNextInPreOrder(TreeNode node, int key) {
if (node == null) {
return;
}
if (node.value == key) {
if(node.left != null){
System.out.print("Next is on left: " + node.left.value);
} else if (node.right != null){
System.out.print("Next is on right: " + node.right.value);
} else {
System.out.print("There is no next node.");
}
}
findNextInPreOrder(node.left); /* then recur on left subtree */
findNextInPreOrder(node.right); /* now recur on right subtree */
}
Thank you!! I also added an 'else' statement since that seemed to help me a bit with the implementation:
void findNextInPreOrder(Node node, int key) {
if (node == null) {
return;
}
if (node.value == key) {
if (node.left != null) {
System.out.print("Next is on left: " + node.left.value);
} else if (node.right != null) {
System.out.print("Next is on right: " + node.right.value);
} else {
System.out.print("There is no next node.");
}
} else {
findNextInPreOrder(node.left, key);
/* then recur on left subtree */
findNextInPreOrder(node.right, key);
/* now recur on right subtree */
}
}

storing information in nodes traversing them

I was tasked to create a tree that stores fibonacci numbers. I previously recycled some code used to create a tree full of names and the key for each node. I can't seem to figure out why when I perform any traversal it doesn't print out the key of the node and value stored. I feel like I am missing something so simple. Well thank you for your time! OR maybe I am misunderstanding the assignment. I do not expect a direct answer since this is pertaining to my education!
original instructions
Create a binary tree that stores your calls. How many calls will each internal node make? How many internal nodes will you have for a recursive version of the solution? Now, how big is that number? What if you call 5 ā€œnā€ and think of Fib(n). What is the runtime complexity of your solution? Do you think you can do better if you simply do away with the recursion and calculate the Fibonacci series iteratively? Write a non-recursive solution and perform a similar analysis on it. How many lines of code would you execute in terms of ā€œnā€? Is it better or worse? Why do you think this is true?
class Node {
int key;
int value;
Node leftChild;
Node rightChild;
Node(int key, int value) {
this.key = key;
this.value = value;
}
}
and this is the rest
package bigobinarytree;
public class BigOBinaryTree {
Node root;
public void addNode(int key, int value) {
Node newNode;
newNode = new Node(key, value);
if (root == null) {
root = newNode;
}
else {
Node focusNode = root;
Node parent;
while (true) {
parent = focusNode;
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
if (focusNode == null) {
parent.leftChild = newNode;
return;
}
}
else
{
focusNode = focusNode.rightChild;
if (focusNode == null) {
parent.rightChild = newNode;
return;
}
}
}
}
}
public void inOrderTraverse(Node focusNode) {
if (focusNode != null) {
inOrderTraverse(focusNode.leftChild);
System.out.println(focusNode);
inOrderTraverse(focusNode.rightChild);
}
}
public void preorderTraverse(Node focusNode) {
if (focusNode != null) {
System.out.println(focusNode);
preorderTraverse(focusNode.leftChild);
preorderTraverse(focusNode.rightChild);
}
}
public void postOrderTraverse(Node focusNode) {
if (focusNode != null) {
postOrderTraverse(focusNode.leftChild);
postOrderTraverse(focusNode.rightChild);
System.out.println(focusNode);
}
}
public Node findNode(int key) {
Node focusNode = root;
while (focusNode.key != key) {
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
} else {
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return null;
}
return focusNode;
}
public Node findValue(int value) {
Node focusNode = root;
while (focusNode.value != value) {
if (value != focusNode.value) {
focusNode = focusNode.leftChild;
} else {
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return null;
}
return focusNode;
}
public boolean remove(int key) {
Node focusNode = root;
Node parent = root;
boolean isItALeftChild = true;
while (focusNode.key != key) {
parent = focusNode;
if (key < focusNode.key) {
isItALeftChild = true;
focusNode = focusNode.leftChild;
} else {
isItALeftChild = false;
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return false;
}
if (focusNode.leftChild == null && focusNode.rightChild == null) {
if (focusNode == root)
root = null;
else if (isItALeftChild)
parent.leftChild = null;
else
parent.rightChild = null;
}
else if (focusNode.rightChild == null) {
if (focusNode == root)
root = focusNode.leftChild;
else if (isItALeftChild)
parent.leftChild = focusNode.leftChild;
else
parent.rightChild = focusNode.leftChild;
}
else if (focusNode.leftChild == null) {
if (focusNode == root)
root = focusNode.rightChild;
else if (isItALeftChild)
parent.leftChild = focusNode.rightChild;
else
parent.rightChild = focusNode.rightChild;
}
else {
Node replacement = getReplacementNode(focusNode);
if (focusNode == root)
root = replacement;
else if (isItALeftChild)
parent.leftChild = replacement;
else
parent.rightChild = replacement;
replacement.leftChild = focusNode.leftChild;
}
return true;
}
public Node getReplacementNode(Node replacedNode) {
Node replacementParent = replacedNode;
Node replacement = replacedNode;
Node focusNode = replacedNode.rightChild;
while (focusNode != null) {
replacementParent = replacement;
replacement = focusNode;
focusNode = focusNode.leftChild;
}
if (replacement != replacedNode.rightChild) {
replacementParent.leftChild = replacement.rightChild;
replacement.rightChild = replacedNode.rightChild;
}
return replacement;
}
public static void main(String[] args) {
BigOBinaryTree theTree = new BigOBinaryTree();
int fib1=1, fib2=1, nacci=1;
int key = 0;
for (int i=3; i <= 50; i++ ){
nacci = fib1 + fib2;
fib1 = fib2;
fib2 = nacci;
theTree.addNode(key, nacci);
key++;
}
System.out.println();
System.out.println("preorderTraverse");
System.out.println();
theTree.preorderTraverse(theTree.root);
System.out.println("___________________");
}
}
You were right, it was something simple, which is bittersweet. You've called
System.out.println(focusNode);
However, for Objects (like focusNode), System.out.println() automatically calls that Object's toString() method. For most Objects, that just means print out their Object ID, and also for most Objects, that's not super useful. Not for programs like this at least. The good news, though, is there are two fixes! First, you could override your Node's toString(). Like:
#Override
public String toString() {
return "Key:" + key + " Value:" + value;
}
You'd just put that in the Node class. Then, every time you called System.out.println(focusNode), under the hood it's actually printing the output of your toString() method in the Node class. Alternatively, instead using:
System.out.println(focusNode);
you could just use:
System.out.println("Key:" + focusNode.key + " Value:" + focusNode.value);
You invokes the preorder method in your main method.
if (focusNode != null) {
System.out.println(focusNode);
preorderTraverse(focusNode.leftChild);
preorderTraverse(focusNode.rightChild);
}
Does that give you any output? If you get some output, based on your code it will be only the standard toString() method of the focusNode object. If you want print out field values of the object like the key, you have to access these fields or overwrite the toString() Method. Like:
System.out.println(focusNode.key);

Tree data structure addnode

I am having issue in understanding the following code. It is a tree data structure and I don't understand why do we need two node (parent and focusnode) in the addnode() method. I tried to do it with just focusnodebut it doesn't work out. My idea is set focusnode to root, and keep looping it until focusnode is equal to null, and set focusnode to newnode.
public class tree {
node root;
public class node{
private int key;
private node left;
private node right;
node(int key){
this.key = key;
}
public int getkey(){
return key;
}
public node getleft(){
return left;
}
public node getright(){
return right;
}
}
public void addnode(int key){
node newnode = new node(key);
if(root == null){
root = newnode;
}else{
node focusnode = root;
node parent;
while(true){
parent = focusnode;
if(key < focusnode.key){
focusnode = focusnode.left;
if(focusnode == null){
parent.left = newnode;
return;
}
}else{
focusnode = focusnode.right;
if(focusnode == null){
parent.right = newnode;
return;
}
}
}
}
}
public void runnode(node focusnode){
if(focusnode != null){
runnode(focusnode.left);
runnode(focusnode.right);
System.out.println(focusnode.key);
}
}`
If you are doing the check like this:
if(key < focusnode.key){
focusnode = focusnode.left;
if(focusnode == null){
focusnode = newnode;
return;
}
}
}
You are looping until focusnode is null, then creating a new node, but not attaching it to the the parent node. As a result, when you try to loop again, you can't loop past the root node since it has no children! If you wish to avoid dealing with the parent node variable, you need to check the child in the condition before setting focusnode, and only set focusnode if the child is not null. e.g:
if(key < focusnode.key){
if(focusnode.left == null){
focusnode.left = newnode;
return;
} else {
foucusnode = focusnode.left;
}
}
}
The check is the same for the right side.
Because if you need to assign a new node as parent's .left or .right child (which happens after you find that focusnode == null... meaning .left/.right is null), then you need a reference to that .left/.right child (the reference is from the parent). You can't set focusnode to your newnode, because it will only assign your newnode to focusnode and not toparent.rightorparent.left`.
So you'll set the focusnode reference to your newnode, but the parent's .left/.right child nodes will not reference your newnode.
If you're coming from C/C++ or similar, imagine that all of these variables are pointers. *focusnode is pointing towards the same object that *parent.left is pointing to. Making *focusnode point to a different object will not change what *parent.left is pointing to.
All variables in Java are references (aside from primitives like int/double etc), which are similar to pointers in C/C++.

Insert node recursively

I am trying to insert node in a binary tree using recursive method. But once its out of the method the root becomes the new node and left child and right child are null. With this I'm trying to learn how recursion works. Also, does recursive method always has to return something. Below is the code.
public class BinaryNode {
int key;
BinaryNode left;
BinaryNode right;
public BinaryNode( int key){
this.key = key;
// this.left = left;
//this.right = right;
}
}
public class BinaryTree {
BinaryNode root;
public void insert(int key){
BinaryNode newNode = new BinaryNode(key);
if(root == null){
root = newNode;
}else{
BinaryNode focusNode = root;
BinaryNode parent;
while(true){
parent = focusNode;
if(key<focusNode.key){
focusNode = focusNode.left;
if(focusNode==null){
parent.left= newNode;
return;
}
}else{
focusNode = focusNode.right;
if(focusNode==null){
parent.right= newNode;
return;
}
}
}
}
}
public BinaryNode recursiveInsert(int key, BinaryNode node){
BinaryNode newNode = new BinaryNode(key);
if (node == null){
root = newNode;
}
else{
if(key < node.key){
root.left = recursiveInsert(key, node.left);
}
else{
root.right = recursiveInsert(key, node.right);
}
}
return root;
}
public String toString(){
String toTree = null;
return toTree;
}
public static void main(String[]args){
BinaryTree tree = new BinaryTree();
tree.recursiveInsert(7, tree.root);
tree.recursiveInsert(6, tree.root);
tree.recursiveInsert(4, tree.root);
tree.recursiveInsert(8, tree.root);
tree.recursiveInsert(9, tree.root);
tree.recursiveInsert(5, tree.root);
}
}
The method I'm trying is recursiveInsert. Thanks!!
I suppose the problem comes from
if (node == null){
root = newNode;
}
You are traversing the tree and in the last step you are asking the left/right child of a leaf node. This hasn't one, so it's child is null.
This is the value returned by the recursive calls and in the end, it gets assigned to root.
To fix this, before descending into a node, make sure that child node exists.
Also this is a bit weird
root.left = recursiveInsert(key, node.left);
It should be node and not root.
There are several issues with your code which I won't necessarily go into, because I think they distract from your core questions.
To answer your second question first: No, there's no rule that says that recursive methods have to return anything. It's more important that they know when to terminate.
As for your bug, I think it's probably due to the fact that your insert method always returns and operates on root. You probably mean to modify and return newNode.
This is because your recursiveInsert method always operates on root. Try this instead -
public Node recursiveInsert(Node currentParent, Node newNode) {
if (currentParent == null) {
return newNode;
} else if (newNode.key > currentParent.key) {
currentParent.right = recursiveInsert(currentParent.right, newNode);
} else if (newNode.key < currentParent.key) {
currentParent.left = recursiveInsert(currentParent.left, newNode);
}
return currentParent;
}
Your recursive code should be like this :
public BinaryNode recursiveInsert(int key, BinaryNode node) {
if (node == null) {
return root = new BinaryNode<>(key);
} else {
if (key < node.key) {
if (node.left == null) {
return node.left = newNode;
} else {
return recursiveInsert(key, node.left);
}
} else {
if (node.right == null) {
return node.right = newNode;
} else {
return recursiveInsert(key, node.right);
}
}
}
}
You are acting on root node in your recursive function, you should rather be acting on the node passed to the recursive function.

finding a node location within a BST and adding it to the tree recursively

So i have 3 methods 1 that adds a node to the binary tree using the traverseAdd method, and another method which finds the location of where a value would be placed within the tree based on its parent node. I would like to eliminate the traverseAdd method and use the findLocation method within the add method to add the new value to the BST.
public void add(int val) {
/*Adds a new node to the binary tree after traversing the tree and figuring out where it belongs*/
Node nodeObjToAdd = new Node(val);
if(root == null){
//if node root is not null root = new node value
root = nodeObjToAdd;
}
Node nodeTraversed = root;
traverseAdd(nodeTraversed, nodeObjToAdd);
}
private void traverseAdd(Node node, Node nodeObjToAdd){
/*Traverses tree and finds a place to add the node to be added by comparing values of the left child and right child of the
* focus node*/
if(nodeObjToAdd.value < node.value){
if(node.leftChild == null){
node.leftChild = nodeObjToAdd;
}
else {
//if the val < the root.value set int he constructor
traverseAdd(node.leftChild, nodeObjToAdd);
}
}
else if(nodeObjToAdd.value > node.value) {
if (node.rightChild == null) {
node.rightChild = nodeObjToAdd;
} else {
traverseAdd(node.rightChild, nodeObjToAdd);
}
}
}
public Node findNodeLocation(Node rootNode, int val) {
/*returns where a the Node after which the value would be added.*/
if(val < rootNode.value && rootNode.leftChild != null){
return rootNode.leftChild;
}
if(val >= rootNode.value && rootNode.rightChild != null){
return rootNode.rightChild;
}
else
return this.root;
}
public void add(int val) {
if (root == null) {
root = new Node(val);
}
Node cur = root;
Node next = null;
while (true) {
next = findNodeLocation(cur, val);
if (next != cur) {
cur = next;
} else {
break;
}
}
if (val < cur.value) {
cur.leftChild = new Node(val);
} else {
cur.rightChild = new Node(val);
}
}
I think this should work

Categories