how to check if a tree is complete? - java

this is my class of A binary search tree:
public class BinarySearchTree {
class BSTNode {
int data;
BSTNode rchild;
BSTNode lchild;
//constructor
public BSTNode(int n){
data=n;
lchild=rchild=null;
}
}
private BSTNode root;
private int size;
public BinarySearchTree() {
root = null;
size = -1;
}
public boolean insert(int n) {
if (root == null)
root = new BSTNode(n);
else
insert(n, root);
return true;
}
private void insert(int n, BSTNode r) {
if (r.data > n)
if (r.lchild == null)
r.lchild = new BSTNode(n);
else
insert(n, r.lchild);
else
if (r.data < n)
if (r.rchild == null)
r.rchild = new BSTNode(n);
else
insert(n, r.rchild);
}
}
Actually I am finding a difficulty in writing a method that checks if my tree is a Complete Binary Tree. Can someone provide me with the solution please.
I will follow this definition:
Complete binary tree : Every level except the last level is completely filled and all the nodes are left justified.

You're going to have to modify this a bit for your your implementation of BSTNode, but I believe this should fit your needs. The basic idea is to recursively traverse the tree and make sure that the "complete" property is fulfilled for each subtree.
boolean checkBinaryTreeCompleteness(TreeNode root) {
if (root != null) {
if (root.right == null && root.left == null) {
return true;
}
if (root.right != null && root.left != null) {
return checkBinaryTreeCompleteness(root.left) && checkBinaryTreeCompleteness(root.right);
}
}
return false;
}

Related

How do I switch my remove method in a BST from being recursive to being iterative?

I am wondering how I can switch my remove method from being recursive to being iterative. My recursive method is working perfectly fine, but all my attempts at making it iterative are not. Where am I going wrong and how can I fix it?
So here's my recursive method:
public boolean remove(E someElement) {
return remove(root, someElement);
}
private boolean remove(Node<E> node, E dataItem) {
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val < 0)
return remove(node.left, dataItem);
else if (val > 0)
return remove(node.right, dataItem);
else
return false;
}
BST manipulation is much easier to do iteratively in C/C++ than in Java because of the possibility to get a pointer to a variable.
In Java, you need to treat differently the case where the element is found at the root; in all other cases the node you're considering is either at the left or at the right of it's parent; so you can replace C's pointer (or reference) to pointers with the parent node and a boolean indicating at which side of the parent the current node is:
public boolean remove(E someElement) {
if (root == null) {
return false;
}
int val = someElement.compareTo(root.data);
if (val < 0) {
return remove(root, false, someElement);
} else if (val > 0) {
return remove(root, true, someElement);
} else {
root = removeNode(root);
return true;
}
}
private boolean remove(Node<E> parent, boolean right, E dataItem) {
Node<E> node = right ? parent.right : parent.left;
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val < 0) {
return remove(node, false, dataItem);
} else if (val > 0) {
return remove(node, true, dataItem);
} else {
node = removeNode(node);
if (right) {
parent.right = node;
} else {
parent.left = node;
}
return true;
}
}
I have omitted method removeNode for the time being, right now, we can make the second method iterative:
private boolean remove(Node<E> parent, boolean right, E dataItem) {
while (true) {
Node<E> node = right ? parent.right : parent.left;
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val < 0) {
right = false;
} else if (val > 0) {
right = true;
} else {
node = removeNode(node);
if (right) {
parent.right = node;
} else {
parent.left = node;
}
return true;
}
parent = node;
}
}
Now the method removeNode must remove the top node and return the new top node after removal. If either left or right is null, it can just return the other node, otherwise, we must find a node to replace the topnode, and it can be either the rightmost node of the left subtree, or the leftmode node of the right subtree.
private Node<E> removeNode(Node<E> parent) {
if (parent.left == null) {
return parent.right;
} else if (parent.right == null) {
return parent.left;
}
boolean right = random.nextBoolean();
Node<E> node = right ? parent.right : parent.left;
Node<E> last = removeLast(node, !right);
if (last == null) {
if (right) {
node.left = parent.left;
} else {
node.right = parent.right;
}
return node;
} else {
last.left = parent.left;
last.right = parent.right;
return last;
}
}
private Node<E> removeLast(Node<E> parent, boolean right) {
Node<E> node = right ? parent.right : parent.left;
if (node == null) {
return null;
}
while (true) {
Node<E> next = right ? node.right : node.left;
if (next == null) {
break;
}
parent = node;
node = next;
}
if (right) {
parent.right = node.left;
node.left = null;
} else {
parent.left = node.right;
node.right = null;
}
return node;
}
I'll give you the algorithm, you can try to code it yourself.
You can use a Stack to iterate through the tree.
So here's how you iterate:
push the tree to stack
loop until the stack isn't empty
pop a node
Null check. If null then continue.
push the left and the right sub-tree onto the Stack
Now in the midst of the iteration, you simply need to check if the popped node is the one you are looking for.
Yes? Check if it has children or not.
Has children? Implement the children snatching logic as usual for recursive deletion
Doesn't have children (a.k.a. leaf node)? Simply assign it to null
Break
No? Continue iterating
Although I feel that Trees are by nature recursive and using recursion is simply a better choice in terms of boosting conceptual understanding of the general working principal of this data structure.
As noted in comments, remove as it is now does nothing, and can be safely replaced with return false;.
Assuming that in the else case you want to do something sensible, as in
private boolean remove(Node<E> node, E dataItem) {
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val < 0)
return remove(node.left, dataItem);
else if (val > 0)
return remove(node.right, dataItem);
else
return do_something(node);
}
the standard strategy is to transform it into a tail recursion. Consolidate the multiple recursive calls into a single one, and make it a last statement in the function:
private boolean remove(Node<E> node, E dataItem) {
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val == 0) {
return do_something(node);
}
if (val < 0)
node = node.left;
else
node = node.right;
return remove(node);
}
So far, just a rewrite to achieve a tail recursive form.
Now, any tail recursive function
foo(args) {
if (interesting_condition(args)) {
return do_something_important(args);
}
args = recompute_arguments(args);
return foo(args);
}
could be mechanically transformed into iterative:
foo(args) {
while (!interesting_condition(args)) {
args = recompute_arguments(args);
}
return do_something_important(args);
}
I hope I answered your question.

writing a proper binary tree height function?

I'm trying to write a function that displays the height of my binary search tree which is displayed below. The problem is I'm supposed to write a function that doesn't have any arguments or parameters. This is really stumping me. I tried declaring root outside the parameter list but that didn't work. Any solutions?
int height (Node root){
if (root == null) {
return 0;
}
int hleftsub = height(root.m_left);
int hrightsub = height(root.m_right);
return Math.max(hleftsub, hrightsub) + 1;
}
the method signature provide by my instructor is
int height ()
EDIT:
my full code
import javax.swing.tree.TreeNode;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.ArrayList;
class BinarySearchTree<E extends Comparable<E>> {
public Node<E> root;
public int m_size = 0;
public BinarySearchTree() {
}
public boolean search(E value) {
boolean ret = false;
Node<E> current = root;
while (current != null && ret != true) {
if (current.m_value.compareTo(current.m_value) == 0) {
ret = true;
} else if (current.m_value.compareTo(current.m_value) > 0) {
current = current.m_left;
} else {
current = current.m_right;
}
}
return false;
}
public boolean insert(E value) {
if (root == null) {
root = new Node<>(value);
m_size++;
} else {
Node<E> current = root;
Node<E> parentNode = null;
while (current != null)
if (current.m_value.compareTo(value) > 0) {
parentNode = current;
current = current.m_left;
} else if (current.m_value.compareTo(value) < 0) {
parentNode = current;
current = current.m_right;
} else {
return false;
}
if (current.m_value.compareTo(value) < 0) {
parentNode.m_left = new Node<>(value);
} else {
parentNode.m_right = new Node<>(value);
}
}
m_size++;
return true;
}
boolean remove(E value) {
if (!search(value)) {
return false;
}
Node check = root;
Node parent = null;
boolean found = false;
while (!found && check != null) {
if (value.compareTo((E) check.m_value) == 0) {
found = true;
} else if (value.compareTo((E) check.m_value) < 0) {
parent = check;
check = check.m_left;
} else {
parent = check;
check = check.m_right;
}
}
if (check == null) {
return false;
} else if (check.m_left == null) {
if (parent == null) {
root = check.m_right;
} else if (value.compareTo((E) parent.m_value) < 0) {
parent.m_left = check.m_right;
} else {
parent.m_right = check.m_right;
}
} else {
Node<E> parentofRight = check;
Node<E> rightMost = check.m_left;
while (rightMost.m_right != null) {
parentofRight = rightMost;
rightMost = rightMost.m_right;
}
check.m_value = rightMost.m_value;
if (parentofRight.m_right == rightMost) {
rightMost = rightMost.m_left;
} else {
parentofRight.m_left = rightMost.m_left;
}
}
m_size--;
return true;
}
int numberNodes () {
return m_size;
}
int height (Node root){
if (root == null) {
return 0;
}
int hleftsub = height(root.m_left);
int hrightsub = height(root.m_right);
return Math.max(hleftsub, hrightsub) + 1;
}
int numberLeafNodes(Node node){
if (node == null) {
return 0;
}
else if(node.m_left == null && node.m_right == null){
return 1;
}
else{
return numberLeafNodes(node.m_left) + numberLeafNodes(node.m_right);
}
}
void display(String message){
if(root == null){
return;
}
display(String.valueOf(root.m_left));
display(String.valueOf(root));
display(String.valueOf(root.m_right));
}
}
class Node<E> {
public E m_value;
public Node<E> m_left;
public Node<E> m_right;
public Node(E value) {
m_value = value;
}
}
If you traverse the tree iteratively, you can get the height without recursion. Anything recursive can be implemented iteratively. It may be more lines of code though. This would be a variation of level order graph / tree traversal.
See: https://www.geeksforgeeks.org/iterative-method-to-find-height-of-binary-tree/
If you use that implementation, delete the parameter, as height() will already have access to root.
This however requires a queue and is O(n) time and O(n) space.
height() may be a public method that calls a private method height(Node node) that starts recursion. O(n) time, O(1) space for BST.
You can pass height as an extra parameter where recursively inserting into the tree so that you are counting the number of recursive calls (which is directly correlated with the depth / # of levels down in the tree you are). Once a node finds it's place, if the height (# of recursive calls) you were passing exceeds the instance variable height stored by the tree, you update the instance variable to the new height. This will also allow tree.height() to be a constant time function. O(1) time, O(1) space.

How can I delete the root node during recursive operation in Binary tree?

I am writing the delete function of Binary tree. I have divided my cases into 3. One with both child null. One with one child null and one with both childs not null. I am recursively calling the delete operation after case 3. For ex, as you can see I have called delete operation on node 50. This would replace the parent node 50 with 75. Now I have to delete the node 75 from right subtree. So I ran the delete procedure recursively. But I am not getting the desired output because 75 is the root node in right subtree of 50. How do I fix it so that I am able to delete the root
class BST {
public static void main(String args[]) {
Tree tr;
tr = new Tree(100);
tr.insert(50);
tr.insert(125);
tr.insert(150);
tr.insert(25);
tr.insert(75);
tr.insert(20);
tr.insert(90);
tr.delete(50);
}
}
class Tree {
public Tree(int n) {
value = n;
left = null;
right = null;
}
public void insert(int n) {
if (value == n)
return;
if (value < n)
if (right == null)
right = new Tree(n);
else
right.insert(n);
else if (left == null)
left = new Tree(n);
else
left.insert(n);
}
public Tree min() {
if(left == null)
return this;
else
return left.min();
}
public Tree max(){
if(right == null)
return this;
else
return right.max();
}
public Tree find(int n)
{
if(n == value)
return this;
else if(n > value)
return right.find(n);
else if(n < value)
return left.find(n);
else
return null;
}
public Tree findParent(int n, Tree parent)
{
if(n == value)
return parent;
else if(n > value)
return right.findParent(n, this);
else if(n < value)
return left.findParent(n, this);
else
return null;
}
public void case1(int n, Tree tr, Tree parent)
{
if(parent.left.value == n)
parent.left = null;
else
parent.right = null;
}
public void case2(int n, Tree tr, Tree parent)
{
if(parent.left!=null && parent.left.value == n)
parent.left = parent.left.left;
else
parent.right = parent.right.right;
}
public void case3(int n, Tree tr, Tree parent)
{
int min = tr.right.min().value;
tr.value = min;
tr.right.delete(min);
}
public void delete(int n) {
// fill in the code for delete
Tree tr = find(n);
Tree parent = findParent(n, this);
if(tr == null)
{
System.out.println("The tree is not present in Binary Tree");
return;
}
if(tr.left == null && tr.right == null)
{
case1(n, tr, parent);
}
else if((tr.left == null) || (tr.right == null))
{
System.out.print(tr.right.value);
System.out.print(parent.right.value);
case2(n, tr, parent);
}
else
{
case3(n, tr, parent);
}
}
protected int value;
protected Tree left;
protected Tree right;
}
Well, you have two options:
First way: you can wrap the tree structure in an object that hides the implementation details of this datastructure. Forward all the relevant modifying calls to the root node, and implement the delete operation to handle the case when the root node should be deleted: in this case you can just replace the reference in the wrapper object.
Second way: Reuse what you have. Don't delete the root node, but overwrite it with the desired new contents. That way you don't have to find and alter the parent of a node, and the problem is solved. This seems much easier though.

Removal not working for BST in java

I'm writing a code for implementing BST in java. My insert, search, search for inorder successor, inorder traversal work fine but when I remove a node, it is not actually removed. Consider the simplest case where the node to be removed is a pendant node. Even if I set this node to null, it is still printed in inorder traversal after deletion. Can anyone please help? Thank you.
package pack_l;
class BSTNode
{
int key;
BSTNode left;
BSTNode right;
BSTNode(int key)
{
this.key = key;
this.left = this.right = null;
}
}
class BST
{
BSTNode root;
BST()
{
root = null;
}
/*insert a node at proper position*/
void insert(BSTNode n)
{
if(root == null)
root = n;
else
{
BSTNode node = root;
while(node != null)
{
if(node.key > n.key)
{
if(node.left == null)
{
node.left = n;
return;
}
else
node = node.left;
}
else
{
if(node.right == null)
{
node.right = n;
return;
}
else
node = node.right;
}
}/*End of while-loop*/
}
}
/*Search a node in the whole tree*/
BSTNode search(int val)
{
BSTNode node = root;
while(node != null)
{
if(node.key == val)
return node;
else if(node.key > val)
node = node.left;
else
node = node.right;
}
return null;
}
/*Remove a node from the tree*/
boolean remove(int val)
{
BSTNode delNode = search(val);
/*If the node is not in the BST*/
if(delNode == null)
return false;
/*If the node has no child*/
if(delNode.left == null && delNode.right == null)
delNode = null;
return true;
}
void inorder(BSTNode root)
{
if(root == null)
return;
inorder(root.left);
System.out.print(" " + root.key + " ");
inorder(root.right);
}
}
public class BSTree {
public static void main(String[] args) {
BST tree = new BST();
BSTNode n1 = new BSTNode(15);
tree.insert(n1);
System.out.println("Before:");
tree.inorder(tree.root);
tree.remove(15);
System.out.println("\nAfter:");
tree.inorder(tree.root);
}
}
Setting delnode = null does nothing: you have a local copy of the reference to a node, and you changed it to refer to null. That doesn't change the actual node in memory at all.
Instead, you must find its parent and set that parent's left or right reference (depending on which is the node to delete) to null.

Node not added to tree

I've been trying to create a integer binary search tree with Java and for some reason, I've been going wrong with adding new nodes to the tree.
Here is the NODE class.
class NODE
{
NODE left = null, right = null;
int info;
public NODE(int x)
{
info = x;
}
}
and here's the BST(Binary Seatch Tree) class with the insert() method.
class BST
{
NODE tree = null;
public void insert(int x)
{
NODE node = new NODE(x);
NODE temp = tree;
while(true)
{
if(temp == null)
{
temp = node;
break;
}
else if(temp.info > x) temp = temp.left;
else temp = temp.right;
}
}
//other methods present here
}
For reasons that I could not figure out, the insert() method is going wrong.
The object tree carries null in it even after the insert() method is called.
Can you find something spotty in the code?
Thanks!
Use a recursive insert method in the NODE class (instead of utilizing an infinite loop as you did):
public void insert(int x) {
if(x < this.info) {
if(this.left == null)
this.left = new NODE(x);
else
this.left.insert(x);
}
else {
if(this.right == null)
this.right = new NODE(x);
else
this.right.insert(x);
}
}
And your BST class would have the following insert method (simply calls the other insert method):
public void insert(int x) {
if(tree == null)
tree = new NODE(x);
else
tree.insert(x);
}
The main insert method is in the NODE class because it must recursively call itself on nodes within the tree.
Of course tree remains null - you don't assign anything to this field.
After temp = tree; and temp = node; only temp is changed, not tree.
The insert() method should insert the child of a node into the tree, calling an already declared Node as a parameter. e.g.:
//Returns true/false depending on whether the insert is successful
public boolean insert(int x, Node node, boolean leftChild) {
if (node == null) return false;
Node child = new Node(x);
if (leftChild) {
if (node.left != null) return false;
node.left = child;
} else {
if (node.right != null) return false;
node.right = child;
}
return true;
}

Categories

Resources