Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add solution for BinarySearchTree #11

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions Session08/binarytree/solutions/BinarySearchTree.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// This class fails to compile, can you figure out why, and fix it?

/* This is beacuse BinaryTree has a constructor which is not default.
Hence, when we extend this class and try to call a no-argument constructor, it'll give a compile-time error.
So, we call it by passing the parameters (to instantiate the root node) in super() called inside the constructor of BinarySearchTree.
*/

class BinarySearchTree extends BinaryTree {

public BinarySearchTree() {
// initialize root to null
super(-1);
}

@Override
public boolean insert(int value) {
super.root = insert(super.root, value);
if(exists(value) == true) return true;
else return false;
}

public TreeNode insert(TreeNode root, int data) {
// if current node is null, insert node with data
if (root == null) {
root = new TreeNode(data);
}

else {
// traverse to left sub-tree if value to be inserted is lesser than or equal to the value in the current node
if (data <= root.getData()) root.left = insert(root.left, data);
// traverse to right sub-tree if value to be inserted is greater than value in current node
else root.right = insert(root.right, data);
}
return root;
}

@Override
public boolean delete(int value) {
TreeNode node = deleteRecursive(super.root, value);
if(node == null) {
return false;
}
else {
super.root = node;
return true;
}
}

public TreeNode deleteRecursive(TreeNode root, int key) {
// if tree is empty, return null
if (root == null) {
return null;
}

// traverse to left sub-tree if value to be inserted is lesser than value in current node
if (key < root.data) {
root.left = deleteRecursive(root.left, key);
}

// traverse to right sub-tree if value to be inserted is greater than value in current node
else if (key > root.data) {
root.right = deleteRecursive(root.right, key);
}

// if value is same as current value, delete it
else {
// node with only one child or no child
if (root.left == null) return root.right;
else if (root.right == null) return root.left;

// if node has two children, get the lowest inorder successor from the right subtree
root.data = minValue(root.right);
// Delete the inorder successor
root.right = deleteRecursive(root.right, root.data);
}
return root;
}

// find the lowest value in the tree by reaching the leftmost leaf node
int minValue(TreeNode root) {
int minv = root.data;
while (root.left != null) {
minv = root.left.data;
root = root.left;
}
return minv;
}

@Override
public boolean exists(int find) {
TreeNode tn = search(super.root,find);
if(tn == null) {
return false;
}
else {
return true;
}
}

public TreeNode search(TreeNode root, int key) {
// not found
if(root==null) {
return null;
}
// if found, return root
if (root.data==key) {
return root;
}

// traverse to left sub-tree if value to be inserted is lesser than value in current node
if (root.data > key) {
return search(root.left, key);
}
// traverse to right sub-tree if value to be inserted is greater than value in current node
return search(root.right, key);
}

@Override
public TreeNode lowestCommonAncestor(int value1, int value2) {

TreeNode tn = lca(super.root, value1,value2);
if(tn == null) return null;
else return tn;
}

// The node value present in between a and b is the lca.
public TreeNode lca(TreeNode root, int a, int b) {

if(root == null) {
return null;
}

if(root.data>b && root.data>a) lca(root.left,a,b);
else if(root.data<b && root.data<a) lca(root.right,a,b);

return root;
}
}
79 changes: 79 additions & 0 deletions Session08/binarytree/solutions/BinaryTree.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
abstract class BinaryTree {
protected TreeNode root;

/* While this constructor cannot be called directly,
it is useful because the child classes can use it,
by using super(), to instantiate the root node
*/
public BinaryTree(int rootValue) {
if(rootValue == -1) this.root = null;
}

public void inOrderTraversal() {
//TODO
inorderRecursive(root);
}

public void preOrderTraversal() {
//TODO
preorderRecursive(root);
}

public void postOrderTraversal() {
//TODO
postorderRecursive(root);
}

// inorder traversal - left,visit,right
void inorderRecursive(TreeNode root) {
if (root != null) {
inorderRecursive(root.left);
System.out.println(root.data);
inorderRecursive(root.right);
}
}

// preorder traversal - visit,left,right
void preorderRecursive(TreeNode root) {
if (root != null) {
System.out.println(root.data);
preorderRecursive(root.left);
preorderRecursive(root.right);
}
}

// postorder traversal - left,right,visit
void postorderRecursive(TreeNode root) {
if (root != null) {
postorderRecursive(root.left);
postorderRecursive(root.right);
System.out.println(root.data);
}
}

/*NOTE: Think about why these methods are abstract.
Why can't we just implement them like we did for the traversals?
*/

/* Insert a node with the given value into the tree
Return true if the insert succeeds, else return false.

This is a signature similar to the one we saw in the CFW.
*/
public abstract boolean insert(int value);

/* Delete the node with the given value from this tree, and
return the deleted node. Return null if the value doesn't exist.
*/
public abstract boolean delete(int value);

/* Return true if the given value exists in the tree
*/
public abstract boolean exists(int find);

/* Return the node that is the LCA of the two given values.

Return null if either or both of the values doesn't exist in the tree.
*/
public abstract TreeNode lowestCommonAncestor(int value1, int value2);
}
17 changes: 17 additions & 0 deletions Session08/binarytree/solutions/TreeNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class TreeNode {
TreeNode left;
TreeNode right;

int data;

public TreeNode(int data) {
this.data = data;
this.left = null;
this.right = null;
}

// get data from node
public int getData() {
return data;
}
}