Construction tree - java

I wrote a tree construction method. I don't see any errors when running it. However, when I'm testing the tree if it is symmetric or not and should return false (for input: [1,2,2,4,4, null, 6]) This means that I am putting root node as 1, second level: 2,2 third level: 4, 4, null, 6. It is returning true. I'm not sure what's wrong? I'm sure that my symmetric function is correct, I just don't know what's wrong with my tree construction? I tried debugging and I saw all the values in the array were implemented in the construction. Can someone let me know what's going on?
public class isSymmetric {
public static class TreeNode {
public int key;
public TreeNode left;
public TreeNode right;
public TreeNode(int key) {
this.key = key;
this.left = this.right = null;
}
}
public boolean symmetric(TreeNode root) {
...
}
//Tree test cases
public static TreeNode construction(Integer[] array) {
//use level order traversal to construct a tree
TreeNode root = new TreeNode(array[0]);
return constructionhelp(array, root, 0);
}
public static TreeNode constructionhelp(Integer[] array, TreeNode root, int i) {
if (root == null) {
return null;
}
if (i < array.length) {
root = new TreeNode(array[i]);
root.left = constructionhelp(array, root.left, 2*i+1);
root.right = constructionhelp(array, root.right, 2*i+2);
}
return root;
}
public static void main(String[] args) {
isSymmetric s = new isSymmetric();
Integer a[] = {1,2,2,4,4,null,6};
TreeNode roota = construction(a);
System.out.print(s.symmetric(roota));
}
}
//returning true;

What happens:
root = new TreeNode(array[i]); // you create new tree node instance
root.left = constructionhelp(array, root.left, 2*i+1); // root.left is null
root.right = constructionhelp(array, root.right, 2*i+2) // root.right is null
so after you call your constructionhelp again, you pass null as an argument of the node.
-> null is returned.
-> your tree is only the root.

Related

Construct a Binary Search Tree from String of Integer

In the class containing the main function, define a function call createTree(String strKey). Giving a string of integers (separated by a space character), this function will create a BST tree with the keys of integers following the input string.
Example: Given a string s = "30 20 40". Calling the function createTree(s) to create a binary seach tree: root = 30, root.left = 20, root.right = 40.
Below is my code:
Node.java
public class Node {
Integer key;
Node left, right;
public Node(Integer key){
this.key = key;
this.left = this.right = null;
}
}
BST.java
public class BST {
private Node root;
public BST(){
this.root = null;
}
public Node getRoot(){
return this.root;
}
public Node insert(Node x, Integer key){
if (x == null){
return new Node(key);
}
int cmp = key.compareTo(x.key);
if (cmp < 0){
x.left = insert(x.left,key);
}
else if (cmp > 0){
x.right = insert(x.right,key);
}
else {
x.key = key;
}
return x;
}
}
Test.java
public class Test {
public static BST createTree(String strKey){
String[] spl = strKey.split(" ");
BST tree = new BST();
Node root = null;
for (int i=0; i<spl.length; i++){
Integer key = Integer.parseInt(spl[i]);
tree.insert(root,key);
}
return tree;
}
public static void main(String[] args){
String s = "20 30 40";
BST tree = createTree(s);
System.out.println(tree.getRoot());
}
}
The result is also null (the root is null) and I don't know the reason why the key is not inserted into the tree. Hope you guys can help me to solve this problem. Thanks a lot
if (x == null){
return new Node(key);
}
The returned node is not assigned to the root in the BST class. Also, you have a root in the createTree method.
You can change it to include an overloaded insert function which takes only the integer to insert and make the existing one private.
private Node insert(Node x, Integer key){
//your existing code
}
public void insert(Integer key) {
this.root = insert(this.root, key);
}
With this, the root will be updated when it is created the first time.
From createTree call the one argument insert method.
public static BST createTree(String strKey) {
String[] spl = strKey.split(" ");
BST tree = new BST();
for (int i = 0; i < spl.length; i++) {
Integer key = Integer.parseInt(spl[i]);
tree.insert(key);
}
return tree;
}

By using this BST insertion method I have only root as output,why?

I am trying to insert in a binary search tree using recursion and then print it preorderly using this specific code, but I have only root as output,why?Is this because each time stack(after each call) is popping off thus removing new nodes?(This is a java code)
class node{
int data;
node left;
node right;
node(int key){
data = key;
left = right = null;
}
}
class bst{
node root;
node temp;
node last;
bst(){
root = null;
}
bst(int key){
root = new node(key);
}
void Insert(node r,int value){
temp = r;
if(temp == null){
if(root == null){
root = new node(value);
root.data = value;
return;
}
temp = new node(value);
temp.data = value;
return;
}
else{
if(value > temp.data){
Insert(temp.right,value);
return;
}
else{
Insert(temp.left,value);
return;
}
}
}
}
class test{
static void in_order(node root){
if(root == null){
return;
}
in_order(root.left);
System.out.println(root.data+" ");
in_order(root.right);
}
public static void main(String[] args){
bst tree = new bst();
tree.Insert(tree.root,45);
tree.Insert(tree.root,39);
tree.Insert(tree.root,12);
tree.Insert(tree.root,59);
test.in_order(tree.root);
}
}
The reason you are only getting a single integer for an output is because the first Insert call correctly adds the element to the tree, but subsequent calls fail because you overwrite the data member temp to null when you recursively insert to the left or right. Thus the second branch of your first if statement never gets executed.
You don't actually need the variable temp here. A common convention is to have a private, recursive member function that takes the root of the tree as a parameter returns the modified tree, and assign the return value to root in a public member function.
public void Insert(int value) {
root = Insert(root, value);
}
private node Insert(node r, int value) {
if (r == null) {
r = new node(value);
}
else if (value > r.data) {
r.right = Insert(r.right, value);
}
else {
r.left = Insert(r.left, value);
}
return r;
}
This means that you only have to call it like tree.Insert(x).

binarysearch tree tree.root returns null

I found binary search tree insertion java code on the website,
https://www.geeksforgeeks.org/binary-search-tree-set-1-search-and-insertion/
and part of the code is like below,
if (root == null) {
root = new Node(key);
return root;
}
and I thought we don`t need any return statement because root itself is reference type(Node), so updating root is enough.
so I changed the code like this.
class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
Node root;
BinarySearchTree() {
root = null;
}
void insert(int key) {
insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
void insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
}
if (key < root.key)
insertRec(root.left, key);
else if (key > root.key)
insertRec(root.right, key);
}
// Driver Program to test above functions
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
tree.insert(50);
tree.insert(20);
System.out.println(tree.root);
}
}
but tree.root returns null.
why is this happening?
root = new Node(key); updates a local variable, it doesn't update the root of the tree (this.root), and it shouldn't. Therefore this assignment doesn't update the tree.
When you return the newly created Node (as in the original code that you changed did), you can assign it to be either the root of the tree (as the original code did with root = insertRec(root, key);) or the left or right child of an existing tree node (as the original code did with root.left = insertRec(root.left, key); or root.right = insertRec(root.right, key);). That's how the tree is updated.
EDIT: Java is a pass by value language, not pass by reference. When you pass a variable to a method, that method can't change the value of the passed variable. If you pass a variable whose value is null to a method, and that method assigns a value to it, the variable will still contain null once the method returns.
Like others already have pointed out, you need to update your root every time you insert an element.
Just return the value of root and update your global root for the tree.
Node insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
return root;
}
if (key < root.key)
root.left = insertRec(root.left, key);
else
root.right = insertRec(root.right, key);
return root;
}
Finally, update your global root.
tree.root = tree.insert(50);
tree.root = tree.insert(20);
Full code:
class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
Node root;
BinarySearchTree() {
root = null;
}
Node insert(int key) {
return insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
return root;
}
if (key < root.key)
root.left = insertRec(root.left, key);
else
root.right = insertRec(root.right, key);
return root;
}
// Driver Program to test above functions
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
tree.root = tree.insert(50);
tree.root = tree.insert(20);
System.out.println(tree.root.key);
}
}
/* A recursive function to insert a new key in BST */
void insertRec(Node root, int key) {
if (root == null) {
root = new Node(key);
}
}
It is called "shadows effect".
That mean your root note from parent class is shadowed by root node in your method.
To fixed it use "this.root" to reference to parent class and initialized the object.
More information : read "Shadowing" in the article. It explained very well.
http://ocpj8.javastudyguide.com/ch03.html
In your constructor you don't initialise a rootNode. Your key is also not transformed in a Node and you don't set your inserted Node to a left or right node. Also you don't do anything with a node that is equal to the current node you traverse.

Convert Binary Search Tree to Doubly Linked List - not working

Solution i am pasting comes from this Geek URL
Its written in C, so i tried converting it in JAVA as below - (please do correct me if m wrong, i am not c/c++ person)
Program
// A simple recursive function to convert a given Binary tree to Doubly
// Linked List
// root --> Root of Binary Tree
// head --> Pointer to head node of created doubly linked list
public void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes head)
{
if(root == null)
return;
// Initialize previously visited node as NULL. This is
// declared outside the recursive function so that the same value
// is accessible in all recursive calls
prev = null;
// Recursively convert left subtree
BinaryTree2DoubleLinkedList(root.getLeft(), head);
//set head of LL if not set
if(orgHead == null)
orgHead = root;
// Now convert this node
if (prev == null)
head = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
BinaryTree2DoubleLinkedList(root.getRight(), head);
}
Tree In Consideration
10
/ \
5 15
/ \ / \
2 7 12 18
/
1
/
0
Problem
This program returns output :
0 1 2 5 7 10 15 18
As you can see, 12 is missing from the code.I tried to dry run it many times but still not able to find out the real issue.....I tried searching for different solutions but most of them traverse in the part-converted-LL which increases the time complexity.
In original C code function prototype is following:
void BinaryTree2DoubleLinkedList(node *root, node **head)
**head mean double pointer, head value can be changed within function using *head. In java you can't modify function parameter because they are always copied, but you can modify array element.
So please try following code:
BTNode prev;
void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes[] head)
{
// Base case
if (root == null) return;
// Initialize previously visited node as NULL. This is
// static so that the same value is accessible in all recursive
// calls
// Recursively convert left subtree
BinaryTree2DoubleLinkedList(roor.getLeft(), head);
// Now convert this node
if (prev == null)
head[0] = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
BinaryTree2DoubleLinkedList(root.getRight(), head);
}
Initial call should look like:
BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
// result is in head[0]
To avoid ugly allocation for head element better to make additional function like following:
BTNodes BinaryTree2DoubleLinkedList(BTNodes root) {
BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
return head[0];
}
Converting Binary Search tree into Doubly Linked List is kind of easy task if we use left and right fields of Node.
Recursion helps us here.
First, go down till the left node. Assign the left most leaf node as prev and also as head of list.
Once control come back from leaf node to its parent, assign current node i.e. parent of left node as right of prev and left of current node as leaf node.
Same is goes for right leaf child of current node.
Once we are out of complete recursion, we will have our doubly linked list, with listHead and listTail.
{
Node prev = null;
Node listHead = null;
Node listTail = null;
public void convertToList(Node node)
{
if(node == null)
return;
convertToList(node.left);
if(listHead == null)
listHead = node;
if(prev == null)
prev = node;
else
{
node.left = prev;
prev.right = node;
}
prev = node;
convertToList(node.right);
if(node.right == null)
listTail = node;
}
public void printList()
{
Node node = listHead;
System.out.println("Doubly Linked List from Head: ");
while(node!= null)
{
System.out.print(node.data+" ");
node = node.right;
}
}
public void printListFromTail()
{
Node node = listTail;
System.out.println("Doubly Linked List from Tail: ");
while(node!= null)
{
System.out.print(node.data+" ");
node = node.left;
}
}
}
For any google visitor, i worked out a way to avoid head[0] - (this might pose problems if the program is called through different object for different trees, as head[0] may get overwritten)
Here is the implementation :
Trick is to remove prev = null; from the code and initialize tempHead = null and prev = null in the calling function, not in recursive call.
void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes tempHead)
{
// Base case
if (root == null) return; //optional, not needed in fact
// Recursively convert left subtree
if(root.getLeft() != null) //purely to reduce number of traversed node
BinaryTree2DoubleLinkedList(root.getLeft(), tempHead);
//set Original Head of the List, this would be leftmost
//leaf in the tree
if(orgHead == null)
orgHead = root;
// Now convert this node
if (prev == null)
tempHead = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
if(root.getRight() != null) //purely to reduce number of traversed node
BinaryTree2DoubleLinkedList(root.getRight(), tempHead);
}
Other helper Details :
Initial call :
BinaryTree2DoubleLinkedList(bst.root,tempHead); //root and null value
Traverse List
printList(orgHead); //pass original head to print function
Complexity :
Time = Space : O(n)
public void ConverttoList(Node root){
Node top = root;
top.left = GetLeftNode(top.left);
top.right = GetRightNode(top.right);
top.left.right= top;
top.right.left= top;
Node leftmost = top.left;
while(leftmost.left!=null){
leftmost = leftmost.left;
}
while(leftmost!= null) {
System.out.printf(leftmost.Data + "->");
leftmost = leftmost.right;
}
}
public Node GetLeftNode(Node root){
if(root.left == null){
return root;
}
else{
Node startnode = GetLeftNode(root.left);
startnode.right = root;
root.left = startnode;
root.right = GetRightNode(root.right);
root.right.left = root;
Node rightmost=root.right;
while (rightmost.right!=null){
rightmost=rightmost.right;
}
return rightmost;
}
}
public Node GetRightNode(Node root){
if(root.left == null){
return root;
}
else{
Node startnode = GetLeftNode(root.left);
startnode.right = root;
root.left = startnode;
root.right = GetRightNode(root.right);
root.right.left = root;
Node leftmost=root.left;
while (leftmost.left!=null){
leftmost=leftmost.left;
}
return leftmost;
}
}
// bst to dll will generate a sorted dll
public class TreeToDLL {
public static void main(String args[]){
TreeNode t = new TreeNode(5);
TreeNode t3 = new TreeNode(3);
TreeNode t1 = new TreeNode(1);
TreeNode t7 = new TreeNode(7);
TreeNode t9 = new TreeNode(9);
TreeNode t8 = new TreeNode(8);
t.setLeft(t3);
t3.setLeft(t1);
t.setRight(t7);
t7.setRight(t9);
t9.setLeft(t8);
DllNode dll = convert(t);
dll.print();
}
static class DllNode{
int data;
DllNode next;
DllNode prev;
public DllNode(int data) {
this.data = data;
}
public DllNode() {
}
public int getData() {
return data;
}
public DllNode getPrev() {
return prev;
}
public void setPrev(DllNode prev) {
this.prev = prev;
}
public void setData(int data) {
this.data = data;
}
public DllNode getNext() {
return next;
}
public void setNext(DllNode next) {
this.next = next;
}
public void print(){
DllNode t = this;
while(t!=null){
System.out.print(t.getData()+"->");
t = t.getNext();
}
}
}
static class TreeNode{
int data;
TreeNode left;
TreeNode right;
public TreeNode(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public TreeNode getLeft() {
return left;
}
public TreeNode setLeft(TreeNode left) {
this.left = left;
return this;
}
public TreeNode getRight() {
return right;
}
public TreeNode setRight(TreeNode right) {
this.right = right;
return this;
}
}
private static DllNode convert(TreeNode t){
DllNode d =convert(t,new PreviousDLLNode());
while(d.prev!=null){
d = d.prev;
}
return d;
}
private static DllNode convert(TreeNode t, PreviousDLLNode d){
if(t==null) return null;
convert(t.getLeft(),d);
DllNode dn = new DllNode(t.getData());
if(d.val!=null){
d.val.setNext(dn);
}
dn.setPrev(d.val);
d.val = dn;
convert(t.getRight(),d);
return dn; // this node will be in the middle of the dll.
}
private static class PreviousDLLNode{
DllNode val;
}
}
I solved my problem inserting treenodes sorted in order in a DLL like that:
I added in my netBeans package the DoubleLinkedList and BinarySearchTree classes needed (including the TreeNode and the DoubleNode etc) and
I modified the BinarySearchTree as shown below:
public class BinarySearchTree {
DoubleLinkedList dL;
TreeNode root;
public BinarySearchTree() {
this.root = null;
this.dL=new DoubleLinkedList();
}
public void
tree2DList(TreeNode TN) {
if (TN == null) {
return ;
} else {
tree2DList(TN.left);
dL.insertLast((YourClassOfObjects)TN.getItem());
tree2DList(TN.right);
}
return;
}
I added a DoubleLinkedList field which I initialized in the default constructor of BST, calling the default constructor of DLL and I created the recursive method below, inspired from and following inOrderTraversal for the sorted input of tree nodes in the DLL

Returning the nth term of an inorder traversal of a binary tree

I came up with this code but it requires a global variable Rank. Is there any way I can solve this problem without having to have a global variable?
int Rank = 0;
public int inOrderTraversal(TreeNode node, int n){
if(node==null)
return 0;
int x=inOrderTraversal(node.left,n);
if(x!=0)return x;
Rank++;
if(n==Rank) return node.data;
int y=inOrderTraversal(node.right,n);
int c= x==0 ? y:x;
return c;
}
I am just trying to return the nth term in an in-order traversal of a binary tree.
You can pass a TraversalState object down the recursion invocation chain, and store the number of nodes that you visited in a variable there:
class TraversalState {
public int rank = 0;
}
...
public int inOrderTraversal(TreeNode node, int n, TraversalState ts){
if(node==null)
return 0;
int x=inOrderTraversal(node.left,n, ts);
ts.rank++;
if(n==ts.rank) return node.data;
int y=inOrderTraversal(node.right,n, ts);
int c= x==0 ? y:x;
return c;
}
Now your implementation is thread-safe, because it does not use "global" objects. Invoke it as follows:
int r = inOrderTraversal(myNode, targetN, new TraversalState());
The recursive approach is easy to understand, but if your tree shape defies expectation, then you're at the mercy of maximum stack depth here, which is likely to be more limiting that heap memory consumed by an explicitly allocated stack structure. Hence, it's better to invest the time in building an iterative walker.
First, define the structure for the tree nodes themselves:
public final class TreeNode {
public final int data;
public final TreeNode left, right;
public TreeNode(int data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
public TreeNode(int data) {
this(data, null, null);
}
}
We're going to want a way to react to events signaled during a depth-first walk through the tree. Returning true from these methods indicates that the visitor wishes for the walk to continue; returning false requests that the walk stop as soon as possible.
public abstract class Visitor {
public boolean visitPre(TreeNode node) {
return true;
}
public boolean visitMid(TreeNode node) {
return true;
}
public boolean visitPost(TreeNode node) {
return true;
}
}
Now, define the iterative in-order walk algorithm:
final class InOrder {
private InOrder() {}
private static final class Breadcrumb {
public final TreeNode node;
public final boolean rightIsNext; // Not a great name.
public Breadcrumb(TreeNode node, boolean rightIsNext) {
this.node = node;
this.rightIsNext = rightIsNext;
}
public static Breadcrumb goingLeft(TreeNode departingPoint) {
return new Breadcrumb(departingPoint, true);
}
public static Breadcrumb goingRight(TreeNode departingPoint) {
return new Breadcrumb(departingPoint, false);
}
}
public static <T extends Visitor> T walk(TreeNode root, T visitor) {
if (null == root ||
null == visitor)
throw new NullPointerException();
final Deque<Breadcrumb> stack = new ArrayDeque<Breadcrumb>();
if (!visitor.visitPre(root))
return visitor;
for (;;) {
for (TreeNode left = root.left;
null != left;
root = left, left = root.left) {
if (!visitor.visitPre(left))
return visitor;
stack.push(Breadcrumb.goingLeft(root));
}
if (!visitor.visitMid(root))
return visitor;
final TreeNode right = root.right;
if (null != right) {
if (!visitor.visitPre(right))
return visitor;
stack.push(Breadcrumb.goingRight(root));
root = right;
} else {
if (!visitor.visitPost(root))
return visitor;
// Go back up the tree until we find a node with an unexplored right child.
for (;;) {
if (stack.isEmpty())
return visitor;
final Breadcrumb breadcrumb = stack.pop();
if (breadcrumb.rightIsNext) {
if (!visitor.visitMid(breadcrumb.node)) {
return visitor;
}
if (null != breadcrumb.node.right) {
if (!visitor.visitPre(breadcrumb.node.right))
return visitor;
stack.push(Breadcrumb.goingRight(breadcrumb.node));
root = breadcrumb.node.right;
break;
}
}
if (!visitor.visitPost(breadcrumb.node))
return visitor;
}
}
}
}
}
Exercise the walk() function on a sample tree:
(1)
|
+-+-+
| |
(2) (5)
|
+-+-+
| |
(3) -
|
+-+-+
| |
- (4)
That is, there are five nodes, where both leaves with data 4 and 5 are right children.
final TreeNode root = new TreeNode(1,
new TreeNode(2,
new TreeNode(3,
null,
new TreeNode(4)),
null),
new TreeNode(5));
walk(root,
new Visitor() {
private final PrintStream ps = System.out;
#Override
public boolean visitPre(TreeNode node) {
trace(node, "Pre");
return true;
}
#Override
public boolean visitMid(TreeNode node) {
trace(node, "Mid");
return true;
}
#Override
public boolean visitPost(TreeNode node) {
trace(node, "Post");
return true;
}
private TreeNode trace(TreeNode node, String phase) {
ps.print(phase);
ps.print('(');
ps.print(node.data);
ps.println(')');
return node;
}
});
This prints the following:
Pre(1)
Pre(2)
Pre(3)
Mid(3)
Pre(4)
Mid(4)
Post(4)
Post(3)
Mid(2)
Post(2)
Mid(1)
Pre(5)
Mid(5)
Post(5)
Post(1)
Now, you asked for a convenient way to find the nth node encountered during an in-order walk. We'll write a function called findNthInOrder(), where the parameter n designates zero as the first node encountered whose left subtree has already been explored, one designates the second, and so on:
private static TreeNode findNthInOrder(TreeNode root, final int n) {
if (n < 0)
throw new IllegalArgumentException();
return walk(root,
new Visitor() {
public TreeNode found = null;
private int remaining = n + 1;
#Override
public boolean visitMid(TreeNode node) {
if (0 == --remaining) {
found = node;
return false;
}
return true;
}
}).found;
}
Calling this function on our sample tree yields the expected result:
final TreeNode nth = findNthInOrder(root, 3);
System.out.println(null != nth ? nth.data : "(none)");
This prints "1" to the console, which matches the previous tracing walk over the sample tree: the fourth (that is, the zero-based index 3, per the argument above) emitted "Mid" trace is for the root node bearing the data value of one.
In summary, consider building enough to formalize the concepts in play, so that you can write these specific queries more confidently atop a sound foundation.
public int inOrderTraversal(TreeNode node, AtomicInteger n){
if(node == null) return 0;
if(n == 0) return node.data;
int leftVal = inOrderTraversal(node.left, n.decrementAndGet());
if(n == 0) return node.data;
int rightVal = inOrderTraversal(node.right,n.decrementAndGet());
return leftVal == 0 ? rightVal : leftVal;
}
Or to use MutuableInt from Apache commons lang instead of AtomicInteger.

Categories

Resources