binary search tree generator - java

I attempted to build a binary search tree builder method. However I think I am missing something. I tested my method with inOrderPrint method and a treeHeigh method. How my method works is that a root node is the first parameter. The second parameter is another TreeNode node. This parameter is a TreeNode and the method should rearrange itself to a binary search tree.
My inOrderPrint is giving me the correct printing which leads me to assume that my buildBST is working. However my treeHeight method is not giving me the correct output. I'm pretty sure my inOrderPrint and treeHeight methods are correctly created.
I believe there is some logic I am missing in my buildBST method but I cant seem to tell what it is.
I have root set as 14.
If I put TreeNodes with values 5,10,3,20,50,25,40,1,2, 18, 100,101, I get a sorted output of those numbers but with treeHeight, I get an output of 5 when I should be expecting 7.
Could someone tell me where I went wrong?
Binary Search Tree generator
code:
public static void buildBST(TreeNode root, TreeNode node) {
if (root == null) {
node = root;
} else {
// less than root
if (node.data < root.data) {
if (root.left == null) {
root.left = node;
} else {
buildBST(root.left, node);
}
}
// greater than root
if (node.data >= root.data) {
if (root.right == null) {
root.right = node;
} else {
buildBST(root.right, node);
}
}
}
}
inOrderPrint:
public static void inOrderPrint(TreeNode node) {
if (node == null) {
return;
} else {
inOrderPrint(node.left);
System.out.println(node.data);
inOrderPrint(node.right);
}
}
treeHeight:
public static int treeHeight(TreeNode node) {
if (node == null) {
return 0;
} else {
int Ldepth = treeHeight(node.left);
int Rdepth = treeHeight(node.right);
return Math.max(Ldepth, Rdepth) + 1;
}
}

14
/ \
5 20
/ /\
3 18 50
/ / \
1 25 100
\ \ \
2 40 101
Height is 5.

The height of the tree is most definitely 5. Easy to see using this little tool
http://algs4.cs.princeton.edu/GrowingTree/

Related

Binary Search Tree : Insertion Wrong Answer

I am trying to write binary search insert method but it gives the wrong answer. I couldn't find what is the reason. Here's my code:
public static Node insert(Node root,int data) {
Node insertedNode = new Node(data);
if(root == null){
root=insertedNode;
}
else {
Node node = root;
Node insertedNode = new Node(data);
while(root.left !=null && root.right !=null){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
if (data > root.data) {
root.left = insertedNode;
}
else {
root.right=insertedNode;
}
}
}
The problem is very easy to detect. Look at your while:
while(root.left !=null && root.right !=null){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
It will only seek to deeper levels if both left and right of root exists. So, let's suppose you try to add 2, 3, 4. You insert 2, which will become your root. Then, you try to add 3. Your while detects that it's not true that both of left and right of root are not null. So, it will add 3 to the right. So far, so good:
2
\
3
Now, you try to add 4. Your while checks whether root.left and root.right are not null. It's false, so it will be the right of the root, resulting in
2
\
4
instead of
2
\
3
\
4
Let's fix your while:
while((root != null) && (((root.data < data) && (root.left != null)) || ((root.data > data) && (root.right != null)))){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}

Binary Tree: Node frequency count for 0, 1, or 2 children

I have an assignment:
You’re given the root node of a binary tree T. We distinguish between 3 types of nodes in T: nodes with 0 children, nodes with 1 child, and nodes with 2 children. Determine, for each type, the number of nodes in T. Return your result as an integer array of length 3.
I am given a Java file that generates random test cases for this algorithm.
I am only allowed to create one function to do all of this. I am not allowed to pass any additional parameters into the method below. I am also not allowed to make any other modifications outside of the function that I create.
In the file, there is a base case already inserted. I have been told to traverse the tree in post-order, using recursion.
I am aware of the current issues with my code. But I don’t know how to fix them.
My current code is as follows:
private static int[] problem1(Node root) {
int[] arr = new int[3];
if (root == null) {
return new int[] {
-1, // nodes with 0 children
-1, // nodes with 1 child
-1 // nodes with 2 children
};
}
//problem1(root.left);
//problem1(root.right);
if (root.left != null && root.right != null) {
arr[2]++;
problem1(root.left);
problem1(root.right);
} else if (root.left != null && root.right == null) {
arr[1]++;
problem1(root.left);
} else if (root.left == null && root.right != null) {
arr[1]++;
problem1(root.right);
} else {
arr[0]++;
}
return arr;
}
The Node class is defined as:
static class Node {
public int value;
public Node left;
public Node right;
}
class Playground {
public static void main(String[ ] args) {
Node root = new Node(1, new Node(2, null, null), new Node(3, null, null));
int[] counts = problem1(root);
System.out.println(counts[0]); // 2 node(s) with 0 children
System.out.println(counts[1]); // 0 node(s) with 1 children
System.out.println(counts[2]); // 1 node(s) with 2 children
}
// recursively count number of childs for each root/node. Post-order
// traversing means both left and right node will be traversed before
// any computations.
public static int[] problem1(Node root) {
// always need a base-case to stop recursive call.
if(root == null) {
return new int[]{0,0,0};
}
// post-order traversing
int[] leftChildCounts = problem1(root.left);
int[] rightChildCounts = problem1(root.right);
int [] counts = new int[]{0,0,0};
counts[0] = leftChildCounts[0] + rightChildCounts[0];
counts[1] = leftChildCounts[1] + rightChildCounts[1];
counts[2] = leftChildCounts[2] + rightChildCounts[2];
if(root.left == null && root.right == null) {
counts[0]++;
} else if(root.left != null && root.right != null) {
counts[2]++;
} else {
counts[1]++;
}
return counts;
}
}
public class Node {
int value;
Node left;
Node right;
public Node(int value, Node left, Node right) {
this.value = 0;
this.left = left;
this.right = right;
}
}
I think you've come pretty close, the only thing you should fix is handling the array of result.
Currently you create a new arr that is supposed to stored the results for every call of problem1 and its wrong because this new array has nothing to do with previously created arrays.
Consider to create it outside the call of problem1 method. You can always pass it as an additional parameter and "accumulate" the result (there is even a term called "accumulator" for this, so arr will be an accumulator).
Think also about the return result (hint: with the accumulator approach you don't really need to return anything)
Since its an assignment, obviously I won't give a full solution leaving to you all the fun ;)

Binary tree adding nodes only in left. How can I make it work both on left and right of the root node?

I recently started learning Data structures and Algorithm. I am creating a binary tree which is adding nodes only on the left of tree. How can I create in such a way that it should add nodes on both the sides of the root node and look like this:
2
/ \
/ \
/ \
/ \
7 5
/ \ / \
/ \ / \
2 6 3 6
Here is the code that I wrote:
public class BinaryTreeOperations {
BinaryTreeNode root;
//let's start with an empty binary tree
public BinaryTreeOperations(){
root = null;
}
//let's initialize our tree with a root node
public BinaryTreeOperations(BinaryTreeNode rootNode){
this.root = rootNode;
}
public void insert(int data)
{
root = insertNode(root, data);
}
private BinaryTreeNode insertNode(BinaryTreeNode node, int data){
//To check if the root is null then create a root node with no children
if (node == null) {
System.out.println("inserting root node"+ data+"\n");
node = new BinaryTreeNode(data);
}
else {
if(node.getRightChild() == null){
System.out.println("inserting right child :"+data+"\n");
node.rightChild=insertNode(node.rightChild, data);
}
else {
System.out.println("inserting left child :"+data+"\n");
node.leftChild = insertNode(node.leftChild, data);
}
}
return node;
}
public int countNodes() {
return countNodes(root);
}
private int countNodes(BinaryTreeNode r) {
if (r == null)
return 0;
else
{
int count = 1;
count += countNodes(r.getLeftChild());
count += countNodes(r.getRightChild());
return count;
}
}
}
Main Class:
public class BinaryTreeMain {
public static void main(String args[]){
BinaryTreeOperations binaryTreeOperations = new BinaryTreeOperations();
binaryTreeOperations.insert(12);
binaryTreeOperations.insert(17);
binaryTreeOperations.insert(11);
binaryTreeOperations.insert(21);
binaryTreeOperations.insert(27);
System.out.println("Total number of nodes :" + binaryTreeOperations.countNodes());
}
}
You can for example store an extra information on each node, like a boolean that gives the direction where to insert, and you switch it after insertion.
It requires only few lines more than what you already did.

Java pointer or node assignment understanding wrong?

A problem I'm solving is asking to insert a node inside a binary search tree, then return the root of the entire binary tree at the end.
The issue I seem to be having is saving the inserted node inside the original tree given it's root. My code is below:
static Node Insert(Node root,int value) {
insertAux(root, value);
return root;
}
static void insertAux(Node root, int value) {
if (root == null) {
root = new Node();
root.data = value;
root.left = root.right = null;
} else {
if (value > root.data) {
insertAux(root.right, value);
} else {
insertAux(root.left, value);
}
}
}
When I test this with the following tree:
4
/ \
2 7
/ \
1 3
it should result in:
4
/ \
2 7
/ \ /
1 3 6
I have tested this and my insertAux function does in fact assign root to a new Node() and the data for that node to the value 6 when it hits the null case at the end of the function. I have also tested and made sure that my Insert function returns the original root at the end of the entire call. However when I try to see if insertAux has assigned root.right.left to a new Node() and its data to 6 inside of the Insert function, I get a null pointer exception where root.right.left is null. Why is this, is my understanding of pointers or node assignment for Java wrong?
static Node insertAux(Node root, int value) {
if (root == null) {
root = new Node();
root.data = value;
root.left = root.right = null;
} else {
if (value > root.data) {
root.right = insertAux(root.right, value);
} else {
root.left = insertAux(root.left, value);
}
}
return root;
}
Your insertAux() method should be like this.
First of all it should have a return type as Node.
What your doing wrong here is that you are not creating a link between the parent node and child node. So in your case, a new Node with data 6 is created but it is actually never assigned to its parent.
So you need to assign the newly created node by returning it and assigning it to parent.In your method here
if (value > root.data) {
root.right = insertAux(root.right, value);
} else {
root.left = insertAux(root.left, value);
}
Java pass parameters by value (i.e not by reference), internal assignment to root is lost after return from function. Try return in different way, maybe
static Node insertAux(Node root, int value) {

Counting the nodes in a binary search tree

I need to create a recursive method that takes as a parameter the root node of a binary search tree. This recursive method will then return the int value of the total number of nodes in the entire binary search tree.
This is what I have so far:
public class BinarySearchTree<E> extends AbstractSet<E>
{
protected Entry<E> root;
//called by the main method
public int nodes()
{
return nodes(root);
}
//nodes() will count and return the nodes in the binary search tree
private int nodes(Entry<E> current)
{
if(current.element != null)
{
if(current.left == null && current.right == null)
{
if(current.element == root.element)
return 1;
deleteEntry(current);
return 1 + nodes(current.parent);
}
else if(current.left != null && current.right == null)
return nodes(current.left);
else if(current.left == null && current.right != null)
return nodes(current.right);
else if(current.left != null && current.right != null)
return nodes(current.left) + nodes(current.right);
} else return 1;
return 0;
}
The main method calls nodes like so:
System.out.println ("\nThis section finds the number of nodes "
+ "in the tree");
System.out.println ("The BST has " + bst.nodes() + " nodes");
So I was running the search by traveling in order, once I'd get to a node with no children I would delete the current node and return to the parent node and continue. I ran a debug of the method I have above and the program crashes with a NullPointerException() when it finally counts and removes all the nodes on the left and right side of the root node and tries to return 1.
This is for my lab, the method MUST be recursive.
I'm very lost at this point, does anyone know what I'm doing wrong?
You are making this way too complicated. The basic idea of object oriented programming is that you trust objects to do the jobs they know the answers to. So if I'm a parent, I can count myself, and I let my children count themselves, and so forth.
private int nodes(Entry<E> current) {
// if it's null, it doesn't exist, return 0
if (current == null) return 0;
// count myself + my left child + my right child
return 1 + nodes(current.left) + nodes(current.right);
}
You have several issues:
You're deleting nodes as you count them? Is nodes() supposed to clear the tree?
You're treating root==null, root!=null&left==null&&right==null, root!=null&left!=null&right==null, etc as separate cases. They're not. You have three cases, which are not entirely exclusive:
If the current node is not null, add one to the count. (This should always be the case. The only case where it might be false is if the current node == root, and we can detect and sidestep that beforehand.)
If the current node has a left child, add the left child's count.
If the current node has a right child, add the right child's count.
You're traversing back up the tree for some ungodly reason. Looks like it has something to do with deleting nodes...?
But the biggest thing in my opinion is, you're not giving enough autonomy to the Entrys. :P
A node can count its own children. Trust it to.
class Entry<E> {
...
int count() {
int result = 1;
if (left != null) result += left.count();
if (right != null) result += right.count();
return result;
}
}
public int nodes() {
return (root == null) ? 0 : root.count();
}
If your teacher is incompetent, and insists on some node-counting function outside a node, you can do the same thing you were trying to do:
private int nodes(Entry<E> current) {
int result = 1;
if (current.left) result += nodes(current.left);
if (current.right) result += nodes(current.right);
return result;
}
public int nodes() {
return (root == null) ? 0 : nodes(root);
}
But that teacher should be fired, in my opinion. The Entry class is the real tree; BinarySearchTree is really just a container for a reference to the root.
Also notice, i don't give a damn about the parents. If we start counting from the root, and each node counts its children, which count their children, etc etc... then all nodes will be accounted for.
public int countNodes(Node root){
// empty trees always have zero nodes
if( root == null ){
return 0;
}
// a node with no leafes has exactly one node
// note from editor: this pice of code is a micro optimization
// and not necessary for the function to work correctly!
if( root.left == null && root.right == null ){
return 1;
}
// all other nodes count the nodes from their left and right subtree
// as well as themselves
return countNodes( root.left ) + countNodes( root.right ) + 1;
}
After you delete current in: deleteEntry(current);, you use current.parent in return 1 + nodes(current.parent);
May be this's the reason of throwing NullPointerException..
Hey I have a very clean counting implemented for a binary tree:
public class Binary<T> where T: IComparable<T>
{
private Node _root;
public int Count => _root.Count;
public void Insert(T item)
{
Node newNode = new Node(item);
if (_root == null)
_root = newNode;
else
{
Node prevNode = _root;
Node treeNode = _root;
while (treeNode != null)
{
prevNode = treeNode;
treeNode = newNode.Item.CompareTo(treeNode.Item) < 1 ? treeNode.Left : treeNode.Right;
}
newNode.Parent = prevNode;
if (newNode.Item.CompareTo(prevNode.Item) < 1)
prevNode.Left = newNode;
else
prevNode.Right = newNode;
}
}
public class Node
{
public T Item;
public Node Parent;
public Node Left;
public Node Right;
public Node(T item, Node parent = null, Node left = null, Node right = null)
{
Item = item;
Parent = parent;
Left = left;
Right = right;
}
public int Count
{
get
{
int count = 1;
count += Left?.Count ?? 0;
count += Right?.Count ?? 0;
return count;
}
}
}
}
Maybe this helps you to understand how to implement a class for a simple binary tree with a count.
This implementation accesses the count through a count in the corresponding node in the tree.
Let me now if you are not familiar with the markup of .NET 4.6

Categories

Resources