Binary Tree in Java without using add method - java

I've been trying to switch over to Java from Node and one thing I'm wondering about is how to construct a Binary Tree without putting a sorting algorithm in. In Node, I could simply type the following:
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
let tree = new TreeNode(4);
tree.left = new TreeNode(2);
tree.left.left = new TreeNode(1);
What is the Java equivalent to this? This is my current thought process
public class BinaryTree {
private static TreeNode root;
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.TreeNode = ??
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}

#EJP: There is no need for two classes. Every tree node is a tree.
OP: Can you show me this with one class.
Based on the code https://stackoverflow.com/a/50072165/139985 ....
public class BinaryTree {
int data;
BinaryTree left, right;
public BinaryTree(int data) {
super();
this.data = data;
this.left = this.right = null; // redundant ...
}
public int height() {
height(this);
}
private int height(BinaryTree node) {
if (node == null) {
return 0;
}
return Math.max(height(node.left), height(node.right)) + 1;
}
public static void main(String[] args) {
BinaryTree tree = new BinaryTree(1);
tree.left = new BinaryTree(2);
tree.right = new BinaryTree(3);
tree.left.right = new BinaryTree(4);
System.out.println("The height of given binary tree is : " + tree.height());
}
}

You can structure your code something like this
class Node {
int data;
Node left, right;
public Node(int data) {
super();
this.data = data;
this.left = this.right = null;
}
}
public class BinaryTree {
Node root;
public int height(Node node) {
if (node == null)
return 0;
return Math.max(height(node.left), height(node.right)) + 1;
}
public static void main(String[] args) {
BinaryTree tree = new BinaryTree();
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(3);
tree.root.left.right = new Node(4);
System.out.println("The height of given binary tree is : " + tree.height(tree.root));
}
}

Related

Transferring a String array to Binary Tree

I'm trying to write a method that can transfer an array into a Binary tree. I know the code is not right, I run it and hope it would show something that I can continue to fix it. But it just kept loading without any error or result. May anyone give me some advice, please!
Here is the BST class:
public class BSTNode {
private String data;
private BSTNode left;
private BSTNode right;
public BSTNode(String data) {
this.data = data;
this.right = null;
this.left = null;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public BSTNode getLeft() {
return left;
}
public void setLeft(BSTNode left) {
this.left = left;
}
public BSTNode getRight() {
return right;
}
public void setRight(BSTNode right) {
this.right = right;
}
}
And my method:
public BSTNode fromArray(String[] array, int start, int end) {
int i = start;
BSTNode root = new BSTNode(array[i]);
BSTNode current = root;
BSTNode parent = null;
while (i <= end) {
if (array[i].compareTo(current.getData()) < 0) {
parent = current;
current.setLeft(current); //Should I put current.setLeft(root) here?
} else {
parent = current;
current.setRight(current);
}
// Create the new node and attach it to the parent node
if (array[i].compareTo(parent.getData()) < 0) {
parent.setLeft(new BSTNode(array[i]));
} else {
parent.setRight(new BSTNode(array[i]));
}
i++;
}
return current;
}
Thank you for your time!
After you've initialized the root, you've already inserted the first element, so you can increment i right away.
You set the left and right pointers without keeping track of the prior value.
You never change the value of current within the loop, and, as you immediately assign it to parent, you don't change parent either.
You should return the root instead of the current node.
How about something like this:
while (++i <= end) {
current = root;
while (current != null) {
parent = current;
if (array[i].compareTo(current.getData()) < 0) {
current = current.getLeft();
} else {
current = current.getRight();
}
}
// Create the new node and attach it to the parent node
if (array[i].compareTo(parent.getData()) < 0) {
parent.setLeft(new BSTNode(array[i]));
} else {
parent.setRight(new BSTNode(array[i]));
}
}
return root;
UPDATE:
You can avoid a redundant comparison by keeping its result in a variable:
while (++i <= end) {
boolean left;
current = root;
do {
parent = current;
left = array[i].compareTo(current.getData()) < 0;
if (left) {
current = current.getLeft();
} else {
current = current.getRight();
}
} while (current != null);
// Create the new node and attach it to the parent node
if (left) {
parent.setLeft(new BSTNode(array[i]));
} else {
parent.setRight(new BSTNode(array[i]));
}
}
return root;
public class Main {
public static final class Node {
public static final String NULL = "_";
public static final String SPLIT = ",";
private final String val;
private Node left;
private Node right;
public Node(String val) {
this.val = val;
}
}
public static void main(String... args) {
Node root = createBinaryTree();
String str = serialize(root); // 0,1,3,7,_,9,_,_,_,4,_,_,2,5,_,8,_,_,6,_,_
Node newRoot = deserialize(str);
}
private static String serialize(Node root) {
StringBuilder buf = new StringBuilder();
serialize(root, buf);
return buf.toString();
}
private static void serialize(Node node, StringBuilder buf) {
if (buf.length() > 0)
buf.append(Node.SPLIT);
if (node == null)
buf.append(Node.NULL);
else {
buf.append(node.val);
serialize(node.left, buf);
serialize(node.right, buf);
}
}
private static Node deserialize(String str) {
String[] values = str.split(Node.SPLIT);
return deserialize(values, new AtomicInteger());
}
private static Node deserialize(String[] values, AtomicInteger i) {
if (i.get() >= values.length)
return null;
String value = values[i.getAndIncrement()];
if (Node.NULL.equalsIgnoreCase(value))
return null;
Node node = new Node(value);
node.left = deserialize(values, i);
node.right = deserialize(values, i);
return node;
}
/*
* 0
* / \
* 1 2
* / \ / \
* 3 4 5 6
* / \
* 7 8
* \
* 9
*/
private static Node createBinaryTree() {
Node[] nodes = { new Node("0"), new Node("1"), new Node("2"), new Node("3"),
new Node("4"), new Node("5"), new Node("6"), new Node("7"),
new Node("8"), new Node("9") };
nodes[0].left = nodes[1];
nodes[0].right = nodes[2];
nodes[1].left = nodes[3];
nodes[1].right = nodes[4];
nodes[2].left = nodes[5];
nodes[2].right = nodes[6];
nodes[3].left = nodes[7];
nodes[5].right = nodes[8];
nodes[7].right = nodes[9];
return nodes[0];
}
}

Merging two binary trees

I want to merge a tree with another tree, t. If there is overlapping data, I want to add them together. This is my code right now. I don't understand how to do this merge function with only parameter t. Doesn't merge usually have two parameters?
public class TreeFunctions {
private TreeNode root;
public TreeFunctions(TreeNode root) {
this.root = root;
}
public TreeNode merge(TreeNode t) {
TreeNode curr = this.root;
if (curr == null) {
return t;
}
if (t == null) {
return curr;
}
curr.data += t.data;
curr.left = merge(t.left);
curr.right = merge(t.right);
return curr;
}
}
public class TreeNode{
TreeNode left;
TreeNode right;
int data;
public TreeNode(int data) {
this.data = data;
}
public TreeNode(int data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
public static String inOrder(TreeNode a) {
if(a == null) return "";
else return inOrder(a.left).trim() + " " + a.data + " " + inOrder(a.right).trim();
}
}
EDIT
My tests for merge:
public void testMerge2() {
TreeFunctions c = new TreeFunctions(new TreeNode(5, new TreeNode(2), null));
TreeNode d = new TreeNode(2, new TreeNode(2), new TreeNode(1));
TreeNode res2 = c.merge(d);
assertEquals(TreeNode.inOrder(res2).trim(), "4 7 1");
}
public void testMerge3() {
TreeFunctions c = new TreeFunctions(new TreeNode(5, new TreeNode(2), null));
TreeNode res2 = c.merge(null);
assertEquals(TreeNode.inOrder(res2).trim(), "2 5");
}
public void testMerge4() {
TreeFunctions c = new TreeFunctions(new TreeNode(1, new TreeNode(2, new TreeNode(5), null), null));
TreeNode res2 = c.merge(new TreeNode(1, null, new TreeNode(2, null, new TreeNode(5))));
assertEquals(TreeNode.inOrder(res2).trim(), "5 2 2 2 5");
}
I've edited my answer per your responses. I believe this is what you want.Please try it and let me know.
In the code, function goes down one level for both t1 and t2 so that merge always takes place on the same level and the same side (left-left/right-right).
public TreeNode merge(TreeNode t) {
TreeNode curr = this.root;
merge2(curr,t);
return curr;
}
public void merge2(TreeNode t1,TreeNode t2) {
if(t2==null)
return;
t1.data += t2.data;
if(t2.left!=null)
{
if(t1.left==null)
t1.left = new TreeNode(0);
merge2(t1.left,t2.left);
}
if(t2.right!=null)
{
if(t1.right==null)
t1.right = new TreeNode(0);
merge2(t1.right,t2.right);
}
}

Binary tree merge?

I am new to stack over flow so sorry for any mistakes, but i am trying to answer this question :
"Write a method that takes two binary trees t1, t2 and a binary tree node v as the arguments. It constructs and returns a new binary tree that has v as its root and whose left subtree is t1 and whose right subtree is t2."
I have done hours of attempts and cant seem to even make 1 binary tree.. The teacher wont really explain and wants us to do it using objects. This is the format she wants us to use.. Can someone please help me..
the commented out stuff is just my attempts to get something to work..
public class treeNode
{
private Object da;
private treeNode left;
private treeNode right;
public treeNode(Object newItem)
{
da = newItem;
left = null;
right = null;
}
public treeNode(Object newItem, treeNode leftNode, treeNode rightNode)
{
da = newItem;
left = leftNode;
right = rightNode;
}
public void setItem(Object newItem)
{
da = newItem;
}
public Object getItem()
{
return da;
}
public void setLeft(treeNode leftNode)
{
left = leftNode;
}
public treeNode getLeft()
{
return left;
}
public void setRight(treeNode rightNode)
{
right = rightNode;
}
public treeNode getRight()
{
return right;
}
//------------------------
public void buildTree()
{
}
//public void combine (l , r)
//{
// T = 5;
// setLeft(l);
// setRight(r);
// return T;
//}
//-----------------------
public static void main (String args [])
{
// treeNode a = new treeNode(5);
// treeNode b = new treeNode(8);
// treeNode c = new treeNode(2);
// a.setLeft(b);
// a.setRight(c);
// System.out.println(a.da);
// System.out.println(a.getLeft() );
// System.out.println(a.getRight() );
// treeNode t = new treeNode();
// t.left = t1;
// t.right = t2;
// System.out.println(buildTree(t));
}
}
My solution consists of two classes: Tree and Node.
The solution can be implemented with just Node, but since you were asked that the function will receive a two trees and a node so I implemented it like this. I don't know if you know java generics(The 'T' I used), if you don't, you can use Object like the code you posted. I'm ignoring all the getters and setters, but of course you can add them.
Node class:
public class Node<T> {
private T data;
private Node right;
private Node left;
public Node(T data) {
this.data = data;
}
public Node(T data, Node right, Node left) {
this.data = data;
this.right = right;
this.left = left;
}
}
Tree class:
public class Tree<T> {
private Node<T> root;
public Tree(Node root) {
this.root = root;
}
public Node<T> getRoot() {
return root;
}
}
The combine function:
public Tree combine(Tree t1, Tree t2, Node v) {
return new Tree(new Node(v, t1.getRoot(), t2.getRoot()));
}

error in creating a balanced binary tree using Java

I wrote this code to create a binary tree but looks like this code is creating an unbalanced binary tree. The nodes are getting only on the right subtree of root. I get Null pointer exception if I try to access child nodes of left subtree. I want to create a balanced binary tree with nodes getting inserted from left to right. What mistake am I doing here and how to rectify it?
public class binTree {
public static class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val){
this.val = val;
this.left = null;
this.right = null;
}
}
public TreeNode root;
public binTree(){
this.root = null;
}
public void insert(int data){
root = insert(root,data);
}
public TreeNode insert(TreeNode node,int data){
if(node == null){
node = new TreeNode(data);
//root = node;
}
else{
if(node.left == null){
node.left = insert(node.left,data);
}
else{
node.right = insert(node.right,data);
}
}
return node;
}
public static void main(String args[]){
binTree obj = new binTree();
obj.insert(5);
obj.insert(11);
obj.insert(13);
obj.insert(1);
obj.insert(7);
obj.insert(21);
obj.insert(35);
System.out.println(obj.root.right.left.val);
System.out.println(obj.root.left.right.val); // this throws null pointer exception
}
}
You'll need to store the quantity of elements for every sub-tree at each tree-node like this:
public class BinTree {
private TreeNode root;
public static class TreeNode {
public int val;
public int elements = 0;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
this.left = null;
this.right = null;
}
}
public BinTree() {
this.root = null;
}
public void insert(int data) {
root = insert(root, data);
}
private static int height(TreeNode node) {
int result = 0;
if (node != null) {
result++;
int total = node.elements;
int heightElements = 2;
while (total > heightElements) {
total -= heightElements;
heightElements *= 2;
result++;
}
}
return result;
}
public TreeNode insert(TreeNode node, int data) {
if (node == null) {
node = new TreeNode(data);
} else if (height(node.left) == height(node.right)) {
node.left = insert(node.left, data);
} else {
node.right = insert(node.right, data);
}
node.elements++;
return node;
}
public static void main(String args[]) {
BinTree obj = new BinTree();
obj.insert(5);
obj.insert(11);
obj.insert(13);
obj.insert(1);
obj.insert(7);
obj.insert(21);
obj.insert(35);
System.out.println(obj.root.val);
System.out.println(obj.root.left.val);
System.out.println(obj.root.right.val);
System.out.println(obj.root.left.left.val);
System.out.println(obj.root.left.right.val);
System.out.println(obj.root.right.left.val);
System.out.println(obj.root.right.right.val);
}
}

Why is the recursive insertion method of the BST not working

I wrote the following code to implement the recursive insert method for the BST. But when I print the tree in walk over order it prints the original tree before insertion. It seems as if the element was not inserted. Please help me out. Thanks in advance. Also please suggest the change in code. By the way, the intial tree in walk over order is 2 5 5 6 7 8.
package DataStructures;
class TreeNode {
private TreeNode parent;
private TreeNode childLeft;
private TreeNode childRight;
private int key;
public TreeNode(){
}
public TreeNode(int key) {
this(key, null);
}
public TreeNode(int key, TreeNode parent) {
this(key, parent, null, null);
}
public TreeNode(int key, TreeNode parent, TreeNode childLeft, TreeNode childRight) {
this.key = key;
this.parent = parent;
this.childLeft = childLeft;
this.childRight = childRight;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getChildLeft() {
return childLeft;
}
public void setChildLeft(TreeNode childLeft) {
this.childLeft = childLeft;
}
public TreeNode getChildRight() {
return childRight;
}
public void setChildRight(TreeNode childRight) {
this.childRight = childRight;
}
}
public class BinarySearchTreeBasicTest {
private static class BinarySearchTree {
private TreeNode root;
private TreeNode maxNode = new TreeNode(0);
public BinarySearchTree(TreeNode root) {
this.root = root;
}
public void printTheTreeInOrderWalk(TreeNode x) {
if (x != null) {
printTheTreeInOrderWalk(x.getChildLeft());
System.out.print(x.getKey() + " ");
printTheTreeInOrderWalk(x.getChildRight());
}
}
public void insertNode(TreeNode node, int key){
if (node == null){
node = new TreeNode(key);
}
else{
if (node.getKey() > key){
insertNode(node.getChildLeft(), key);
} else if (node.getKey() < key){
System.out.println("k");
insertNode(node.getChildRight(), key);
} else{
// dont do anything
}
}
}
}
public static void main(String[] args) {
TreeNode rootNode = new TreeNode(6);
BinarySearchTree tree = new BinarySearchTree(rootNode);
TreeNode node1 = new TreeNode(5);
TreeNode node2 = new TreeNode(7);
rootNode.setChildLeft(node1);
rootNode.setChildRight(node2);
node1.setParent(rootNode);
node2.setParent(rootNode);
TreeNode node3 = new TreeNode(2);
TreeNode node4 = new TreeNode(5);
node1.setChildLeft(node3);
node1.setChildRight(node4);
node3.setParent(node1);
node4.setParent(node1);
TreeNode node5 = new TreeNode(8);
node5.setParent(node2);
node2.setChildRight(node5);
tree.insertNode(rootNode, 3);
tree.printTheTreeInOrderWalk(rootNode);
}
}
In your insertNode() method, you are just creating a new node; you are never adding the newly created node to its parent. You should check whether you are going to insert here or not or you should return the newly returned node and set it accordingly.
If you don't want too much deviation from your current program, you can make the following changes.
public void insertNode(TreeNode node, int key) {
if (node.getKey() > key) {
if (node.left == null) { //check if you want to insert the node here
TreeNode newNode = new TreeNode(key);
node.left = newNode;
} else {
insertNode(node.getChildLeft(), key);
}
} else if (node.getKey() < key) {
if(node.right == null){ //check if you want to insert the node here
TreeNode newNode = new TreeNode(key);
node.right = newNode;
} else {
insertNode(node.getChildRight(), key);
}
} else {
// don't do anything
}
}
In Java, parameters are passed by value. In insertNode, if you don't do anything else with the node, the line node = new TreeNode(key); will not do anything useful.
The typical implementation of an insertion in a tree works by returning the TreeNode that will replace the previous one:
private TreeNode insertNode(TreeNode node, int key){
if (node == null){
node = new TreeNode(key);
}
else{
if (node.getKey() > key){
node.setChildLeft(insertNode(node.getChildLeft(), key));
} else if (node.getKey() < key){
node.setChildRight(insertNode(node.getChildRight(), key));
} else{
// dont do anything
}
}
return node;
}
Going a bit further, the previous method should actually be private. The public method should look like this:
public void insertNode(int key){
root = insertNode(root, key);
}

Categories

Resources