I know this is pretty straight forward code but wondering how exactly the internal working is.
public static int getHeight(TreeNode root) {
if (root == null) {
return 0;
}
System.out.print(getHeight(root.left) +"\t");
return Math.max(getHeight(root.left), getHeight(root.right)) + 1;
}
For my understanding, I added print statement but it results the following.
printing root.left() prints this: 0 0 0 1 0 0 0
printing root.right() prints this: 0 0 2 0 0 3 0 0 2 0 0 0 1 0
Following is the Tree created in the main program:
TreeNode parent = new TreeNode(10);
parent.insertInOrder(2);
parent.insertInOrder(13);
parent.insertInOrder(5);
parent.insertInOrder(6);
parent.insertInOrder(15);
parent.insertInOrder(6);
How is this printing the above result and how is it working. If anyone can explain me with the above example, it would really help me.
I know how traversals work and how to print the tree but I really want to understand the above output. If anyone can help then it would be great.
void setLeftChild(TreeNode left)
{
this.left = left;
if(left == null)
{
left.parent = this;
}
}
void setRightChild(TreeNode right)
{
this.right = right;
if(right == null)
{
right.parent = this;
}
}
void insertInOrder(int d)
{
if(d <= data)
{
if(left == null)
{
setLeftChild(new TreeNode(d));
}
else
{
left.insertInOrder(d);
}
}
else{
if(right == null)
{
setRightChild(new TreeNode(d));
}
else{
right.insertInOrder(d);
}
}
size++;
}
You should create a function that outputs information about the tree. For example, this function does a preorder traversal, showing information about each node:
public static void ShowTree(TreeNode root, TreeNode parent, depth)
{
if (root == null) return;
// output 'depth' spaces.
// The indentation will help show the structure of the tree.
// output node value, and parent (if parent not null)
// Traverse the left node
ShowTree(root.left, root, depth+1);
// Traverse the right node
ShowTree(root.right, root, depth+1);
}
Call that function with ShowTree(tree, null, 0). The resulting output will show the structure of the tree, and you can determine if the tree is balanced. It's a useful thing to have when you're developing tree code because you can do an insert, for example, then call ShowTree to see if the insert worked as expected.
Update
The code's output is a little strange because your print statement results in a recursive call. So every node below the current node ends up getting printed multiple times.
I think you want to do this:
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
// now output output leftHeight or rightHeight, or both
return Math.max(leftHeight, rightHeight) + 1;
That way you won't get the multiple recursive calls that produce the strange output.
More info
The reason you're seeing those extra recursive calls is because you're calling getHeight(root.left) twice. Let's say your tree looks like this:
root
/
child
/
grandchild
So you call getHeight(root). Then:
getHeight(child) is called in your print statement
getHeight(grandchild) is called in your print statement
getHeight(null) is called in your print statement
getHeight(grandchild) prints 0
getHeight(null) is called twice (once for the left node and once for the right node) in the return statement
getHeight(grandchild) returns 1
getHeight(child) prints 1
getHeight(grandchild) is called in the return statement
getHeight(null) is called in your print statement
getHeight(grandchild) prints 0
getHeight(grandchild) returns 1
getHeight(null) (the right node) is called in the return statement
...
You see where the problem is? getHeight(grandchild) is called again! Every time your print statement calls getHeight, it has to walk every descendant node. So the height of every node is output multiple times. The deeper the node is in the tree, the more often it will be output.
The change I suggested in my update above prevents that by ensuring that no node is visited more than once.
Related
The answer needs to be iterative, not recursive and the trees don't have to have the same structure, only the same numbers. I think I need to use a vertex traversal, but I am not sure how to implement that without using recursion.
This is what I had, but it doesn't pass the given tests. Also, I can't use any helper functions.
Node leftTree = t1;
Node rightTree = t2;
if(t1 == null && t2 == null)
return true;
else if (t1 != null && t2 == null)
return false;
else if (t1 == null && t2 != null)
return false;
else
{
if(leftTree.key == rightTree.key && problem1(leftTree.left, rightTree.left) == true
&& problem1(leftTree.right, rightTree.right) == true)
return true;
}
return false;
The recursion, where you compare left with left and right with right, will not work, because you can have the same keys but in a different topology. You need to visit the nodes in-order in the two trees in parallel.
One way of going through a tree without using recursion or extra memory is via a Morris traversal, where you temporarily put a tree in the rightmost position of its left subtree, and "return" from the recursion by following the right pointer there.
Here is an implementation in C, because I have one lying around. In Java it won't be that different. The rightmost_to() function returns the rightmost node in the left child of the current node, or the current node itself. You use it put the current node in the right child there, so when you get down to that point, going right emulates returning from the recursion.
void morris(stree *t)
{
struct node *curr = *t;
while (curr) {
if (!curr->left) {
printf("%d\n", curr->value);
curr = curr->right;
} else {
stree pred = *rightmost_to(&curr->left, curr);
assert(pred->right == 0 || pred->right == curr);
if (pred->right == 0) {
pred->right = curr;
curr = curr->left;
} else {
printf("%d\n", curr->value);
pred->right = 0;
curr = curr->right;
}
}
}
}
You will visit each node in order, without recursion, and without using extra memory. Whenever you recurse, you put the node you are in at the rightmost position, so you automatically come back to it. You can recognise that you are seeing the node for the second time because you find it when searching for the rightmost. Then you restore the tree instead of going left once more.
If you need to compare two trees, have two current nodes, and you should be fine. It does use an extra function, rightmost_to(), but it is a simple loop that you can easily embed without any issues. It is a line or two if you do that.
If you are allowed to put a parent pointer in the nodes, I think you can also traverse the trees without using extra memory doing something like this:
#define left_child(t) \
((t)->parent && (t)->parent->left == (t))
void parent_traverse(stree t)
{
enum { DOWN, UP } state = DOWN;
while (t) {
switch (state) {
case DOWN:
// Recurse as far left as we can...
while (t->left) { t = t->left; }
// Emit the leaf we find there
printf("(,%d,", t->value); // VISIT
// Then go right, if we can, or up if we can't.
if (t->right) { t = t->right; }
else { state = UP; }
break;
case UP:
if (!t->parent) return; // we have returned to the root...
if (left_child(t)) {
// Returning from a left child, we emit the parent
t = t->parent;
printf(",%d,", t->value); // VISIT
// Then we go right if we can't, or continue up
// (t is already the parent) if we cannot.
if (t->right) { t = t->right; state = DOWN; }
} else {
// Returning from a right child just means going up
t = t->parent;
}
break;
}
}
}
Sorry, it is C again, but just look at how t is updated to its left, right or parent node as we run through the tree. I cut that out of some code I have, and I might have copied it wrong, but you should get the idea. You can keep track of which direction you are moving, and essentially move along the "edge" of the tree, down left edges, under them and up, then down to the right, turn, and move up, and so on. If you have the state for both trees, you should be able to do that traversal in parallel in the two. Everwhere the code "visits" a node, you will compare the two nodes.
I don't know how useful this is, but it is at least a couple of ways that you can compare two trees with only constant extra memory usage and no recursion.
Of course, if it is a simple assignment and the time complexity doesn't matter, run through one tree and look up in the other in O(n log n) (balanced) or O(n^2). :)
I am checking if a tree is a binary search tree. I see what the known solution is. Prior to me looking it up, I came up with the following attempt based off of post order traversal. I have traced it by hand, and seems to make sense. But, it is incorrect. Can anyone help me understand why?
class Node {
int data;
Node left;
Node right;
}
boolean checkBST(Node root) {
// Empty tree
if (root == null) {
return true;
}
// Sub trees are BST
boolean valid = checkBST(root.left) && checkBST(root.right);
// Greater than left
if (root.left != null) {
valid = valid && root.data > root.left.data;
}
// Less than right
if (root.right != null) {
valid = valid && root.data < root.right.data;
}
return valid;
}
Your code will fail for this basic test case,as it returns true for following:
50
/
3
/ \
1 100
The problem is your code is only comparing the node with its immediate children and not with the entire subtree. It return true for subtree rooted at 3 and
because 3 < 50, your code finally returns true, which is wrong.
So I got an assignment of creating a BST in Java and so far it has all went well. However I got a question about the remove method. As I have implemented, if I remove node X, all of node X's subtrees will also be deleted. And I just wondered if this is a common implementation, or should I rearrange the nodes if I delete one? I am also to make a AVL tree out of this class, so I will need a trinodeRestructering method. I guess This would need some modification aswell if I go in and deletenodes?
Thiis is how my remove method works:
private TreeNode remove(TreeNode currN, int dataToRemove) {
if (dataToRemove < currN.getData()) {
if (currN.getLeft() != null) {
if (currN.getLeft().getData() == dataToRemove) {
currN.setLeft(null);
} else {
remove(currN.getLeft(), dataToRemove);
}
}
} else if (dataToRemove > currN.getData()) {
if (currN.getRight() != null) {
if (currN.getRight().getData() == dataToRemove) {
currN.setRight(null);
} else {
remove(currN.getRight(), dataToRemove);
}
}
}
return currN;
}
//visual representation
/--------85
/--------25
/--------20
10
********************************************************************
*******removed 20******
10
*******************************************************************
Added tree for post:
/--------85
/--------25
\--------24
/--------20
| /--------13
\--------12
| \--------11
10(root)
Here is some swapping I tried, it looks like really crappy, hard to read code:
if (dataToRemove < currN.getData()) {
if (currN.getLeft() != null) {
if (currN.getLeft().getData() == dataToRemove) {
//Om inga barn, sätt noden till null.
if(currN.getLeft().getLeft() == null && currN.getLeft().getRight() == null){
currN.setLeft(null);
}//Om noden enbart har höger barn
else if(currN.getLeft().getLeft() == null){
TreeNode old = currN.getLeft().getRight();// Gamla höger
currN.setLeft(currN.getLeft().getLeft()); //
currN.getLeft().getRight().setRight((old)); //
}//Om noden enbart har vänster barn.
else if(currN.getLeft().getRight() == null){
TreeNode old = currN.getLeft().getRight();// Gamla vänster
currN.setLeft(currN.getLeft().getLeft()); //
currN.getLeft().getLeft().setRight((old)); //
}//om två barn
else{
TreeNode oldRight = currN.getLeft().getRight();// null
currN.setLeft(currN.getLeft().getLeft()); //sätt current left till 11
currN.getLeft().setRight((oldRight)); // current left, right till 13
}
} else {
remove(currN.getLeft(), dataToRemove);
}
}
yeah there is a known implementation for that , when you want to delete node in the binary search tree you swap it with the right most leaf of its left subtree, or the left most leaf of its right subtree then delete that leaf.
For the AVL you will have to keep track in you recursive operations of the balance condition , whenever that balance condition is violated you will need to do some kind of rotation depending on the structure of this violation , if you do some research you will find a decent amount of resources explaining the exact algorithms for this.
I have the code for printing a the contents of a binary search tree in-order (ascending) using recursion. I understand that the helper method calls on the recursive method with root as the beginning node value. But I don't understand how the recursive code works conceptually. Could anyone explain?
//ascend method that prints values in the tree in ascending order
//recursive method below
public void printAscending() {
printAscending(root);
}
private void printAscending(Node node) {
if(node != null) {
printAscending(node.left);
System.out.println(node.data);
printAscending(node.right);
}
}
Consider the following (trivial) tree:
1
You'd be calling the function on the one (the root) and it is obvious to see that the result is 1.
Now consider the following (slightly larger) tree:
2
1
The root is now 2 and the output (manually traced by hand) gives 1 2. (spaces added for clarity)
Similar manual tracing on the following gives us 1 2 3:
2
1 3
So we can now see that for small testcases, it seems to work fine.
Let's try proving it for larger testcases.
For any null node (i.e. if we are at a non-existant tree/subtree) we just exit.
For any non-null node, the printAscending(node.left) line is called first. This line MUST finish execution before anything else runs. This calls the printAscending() function using node.left as parameter which is equivalent to just looking at the left subtree of the current node, finishing the work there and then continuing the code. We can keep going down the left until we reach a null node. At this point of time, it moves back upwards, resuming from where it had stopped off. It runs System.out.println(node.data) which gives the output of a single node and then runs printAscending(node.right). This causes it to enter the right subtree of the current node. Note that in this subtree, it runs the complete code (i.e. runs the left, center and then right parts). Once it is done running through the right subtree, it backs out of the subtree and the current node. This makes the node just above it (the parent) move on to the next part of the code.
If you follow a similar working, you'll see that the whole left subtree of the root is processed first, then the root is printed and then whole right subtree is processed.
// public entry point, reuses the recursive function
public void printAscending() {
printAscending(root);
}
// print this node and all of its descendants
private void printAscending(Node node) {
// is there actually a node here
// or was this called from a node with no children
if(node != null) {
// print everything that's earlier than this node
printAscending(node.left);
// print this node's value
System.out.println(node.data);
// print everything that's afterthan this node
printAscending(node.right);
}
}
public void printInOrder() {
if (left != null) {
left.printInOrder();
}
System.out.println(data);
if (right != null) {
right.printInOrder();
}
}
i am trying to learn abit about recursive methods and is writing a method for my binary tree that counts the sum of all the integers in the tree my code works fine and all but i am still abit confused about how the application knows when to stop. my code looks like the this:
public int sum(){
return sum(overallRoot);
}
private int sum(IntTreeNode root) {
if (root == null) {
return 0;
}else {
return root.data + sum(root.left) + sum(root.right);
}
}
(the above code is from my nodeTree class)
The next code is from my main class:
public class TreeClient {
/**
* #param args
*/
public static void main(String[] args) {
IntTree tree = new IntTree(12);
System.out.println(tree.sum());
}
}
So the question is (maybe for many quite simple) but how does my application know when to stop? ive tried with simple system out prints to figur out but as far as my understanding is right now the method would call it self in an endless loop?
hope someone has time to respond!
In any recursive program, your iteration stops when a base condition is reached.. Here your base condition is : -
if (root == null) {
return 0;
}
So, when your root.left and root.right, in the following return statement in else block both becomes null, you have reached your base condition, and hence your loop stops..
return root.data + sum(root.left) + sum(root.right);
Pretty simple really
Take the line from the sum function:
return root.data + sum(root.left) + sum(root.right);
When you get to the bottom of the tree, root.left will be null, and so will root.right. Thus, when the above line calls sum(root.left) the sum function drops into the other half of the if statement:
return 0;
Thus, the sum function no longer calls itself, and so stops recursing
The answer is that it does not go into an endless loop because there is a condition when it does not call itself recursively anymore.
The condition is
if (root == null)
when it does
return 0;
rather than calling itself again
return root.data + sum(root.left) + sum(root.right);