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.
Related
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;
}
I have written a Code for AVL Tree Insertion but when I try to print the value of Root Node it always returns Null. I am unable to understand the reason.Anyone who can solve this problem? I have tried many times but I could not resolve the problem. I am confused. I hope that someone from here will help in the case of resolving the problem I have as I am sure there are high level of experts here.
public class AVLTreeMethods {
public Node root = null;
public int height(Node node){
if (node == null)
return 0;
return node.height;
}
public int max(Node node1, Node node2){
if (node1.height > node2.height)
return node1.height;
return node2.height;
}
public Node rotateRight(Node node){
Node newNode = node.left;
node.left = newNode.right;
newNode.right = node;
node.height = max(node.left,node.right) + 1;
newNode.height = max(newNode.left, newNode.right) + 1;
return newNode;
}
public Node rotateleft(Node node){
Node newNode = node.right;
node.right = newNode.left;
newNode.left = node;
node.height = max(node.left,node.right) + 1;
newNode.height = max(newNode.left, newNode.right) + 1;
return newNode;
}
public Node AVLINSERT(int data, Node root){
if (root == null){
return new Node(data);
}
else if (data > root.data){
root.left = AVLINSERT(data, root.left);
}
else if (data < root.data){
root.right = AVLINSERT(data, root.right);
}
int balance = height(root.left) - height(root.right);
if (balance > 1){
if (height(root.left.left) > height(root.left.right)){
return rotateRight(root);
}
else {
root.left = rotateleft(root.left);
return rotateRight(root);
}
}
if (balance < -1){
if (height(root.right.right) > height(root.right.left)){
return rotateleft(root);
}
else
root.right = rotateRight(root);
return rotateleft(root);
}
root.height = 1 + max(root.left, root.right);
return root;
}
public void inorderPrinting(Node root){
inorderPrinting(root.left);
System.out.println(root.data);
inorderPrinting(root.right);
}
public void callingAVLInserting(int data){
AVLINSERT(data,root);
}
public void callinInorderPrinting(){
inorderPrinting(root);
}
}
Just by looking at your code, you have initialised the root to null however, you do not have any constructor that initializes it.
So try add something of the sort.
public class AVLTreeMethods {
public Node root = null;
//add the following
public AVLTreeMethods() {
//initialize your root appropriately e.g.
this.root = new Node(//pass in some data e.g 0)
}
...rest of your code
}
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++.
My code for inserting a node into a BST is not working. When I try to display it shows only the last two nodes of the tree, i.e. it somehow overwrites the nodes in a tree. What did I do wrong? Thanks in advance!
public Node Insert(int value)
{
Node newNode = new Node();
newNode.data = value;
newNode.left = null;
newNode.right = null;
if(root == null){
root = newNode;
return root;
}
else{
while(root != null){
if(root.data < value){
if(root.right != null){
root = root.right;
}
else{
root.right = newNode;
break;
}
}
else{
if(root.left != null){
root = root.left;
}
else{
root.left = newNode;
break;
}
}
}
return root;
}
}
public void inOrder(){
inOrder(this.root);
}
private void inOrder(Node root){
if(root != null){
inOrder(root.left);
System.out.println(root.data);
inOrder(root.right);
}
}
root points to the top node of your tree. In the while you are changing its value. You must use anoter variable (say 'n').
The initial value of 'n' is 'root'.
And inside the while you only use 'n'.
if(root == null){
root = newNode;
return root;
}
else{
Node n = root;
while(n != null){
...
}
return root;
...
You must return 'root', not 'n', because the root don't change.
See my comments in the code . Hope it helps.
public Node Insert(int value)
{
Node newNode = new Node();
newNode.data = value;
newNode.left = null;
newNode.right = null;
if(root == null){
root = newNode;
return root;
}
else{
while(root != null){
if(root.data < value){
if(root.right != null){
root = root.right;
// root should point to the head of the tree.
/* Here you are changing the variable root to point to some other memory location and the reference to the head of the tree is lost. You should store the reference to the head of the tree in a temporary variable to return later */
}
else{
root.right = newNode;
break;
}
}
else{
if(root.left != null){
root = root.left;
//root should point to the head of the tree.
/* Here you are changing the variable root to point to some other memory location and the reference to the head of the tree is lost. You should store the reference to the head of the tree in a temporary variable to return later */
}
else{
root.left = newNode;
break;
}
}
}
// return temporary variable which points to the head of the tree here
return root;
}
}
public void inOrder(){
inOrder(this.root);
}
private void inOrder(Node root){
if(root != null){
inOrder(root.left);
System.out.println(root.data);
inOrder(root.right);
}
}
Here is my Node class:
private class Node {
private int key; // the key field
private Object data; // the rest of the data item
private Node left; // reference to the left child/subtree
private Node right; // reference to the right child/subtree
private Node parent; // reference to the parent
.. and so on.
This is the inorder iterator with next() and hasNext() methods:
private class inorderIterator implements LinkedTreeIterator {
private Node nextNode;
private inorderIterator() {
// The traversal starts with the root node.
nextNode = root;
if(nextNode == null)
return;
while (nextNode.left != null)
nextNode = nextNode.left;
}
public boolean hasNext() {
return (nextNode != null);
}
public int next() {
if(!hasNext())
throw new NoSuchElementException();
Node r = nextNode;
if (nextNode.right != null) {
nextNode = nextNode.right;
while (nextNode.left != null) {
nextNode = nextNode.left;
}
return r.key;
} else while (true) {
if (nextNode.parent == null) {
nextNode = null;
return r.key;
}
if (nextNode.parent.left == nextNode) {
nextNode = nextNode.parent;
return r.key;
}
nextNode = nextNode.parent;
}
return r.key;
}
}
The problem is, it only ever prints the left nodes on the left sub-tree.
For example, for a tree with root node 17, left node 15 and right node 19, it only prints 15.
So it never enters a right subtree.
I'm guessing the problem is with the else while (true) portion, but I can't figure out how to fix this.
You could try a recursive approach.
Something like:
public void printTreeInOrder(Node node){
if(node.left != null){
printTree(node.left);
}
System.out.println(node.key);
if(node.right != null){
printTree(node.right);
}
}
If you passed this method the root node it should print out the entire tree for you.
I hope this helps.
Best.
Turns out that the parent field of my nodes was not being updated properly. Once that was fixed, the iterator worked properly.
I would use a stack with this helper method:
Node advance_to_min(Node r)
{
while (r.left != null)
{
s.push(r);
r = r.left;
}
return r;
}
The first node inorder is given by the call to this method on the root. Something like:
curr = advance_to_min(curr);
And then I would implement next() thus:
void next()
{
curr = curr.right;
if (curr != null)
{
curr = advance_to_min(curr);
return;
}
if (s.is_empty())
curr = null;
else
curr = s.pop();
}
curr and the stack s would be iterator attributes. curr would point to the current node in the inorder sequence.
The cost O(lg n) at worst case for each next() call (if the tree tends to be balanced) and the approach does not require parent pointers; so, it would have the same space cost than using parent pointers but only in the worst case