diff --git a/src/main/java/datastructs/adt/BinarySearchTree.java b/src/main/java/datastructs/adt/BinarySearchTree.java new file mode 100644 index 0000000..a02a3bd --- /dev/null +++ b/src/main/java/datastructs/adt/BinarySearchTree.java @@ -0,0 +1,43 @@ +package datastructs.adt; + +import utils.BSTInsertStratergy; +import utils.IPredicate; +import utils.TreeNode; +import utils.TreeNodeCreator; + +import java.util.Comparator; + +/** + * Implementation of a Binary Search Tree + */ +public class BinarySearchTree extends BinaryTree { + + /** + * Constructor + */ + BinarySearchTree(Comparator comparator){ + super(new BSTInsertStratergy(comparator)); + } + + + /** + * Push a new element in the ADT + */ + @Override + public void push(E element){ + + if(super.root_ == null){ + + this.createRoot(element); + } + else { + + boolean rslt = super.getInsertStrategy().insert(super.root_, super.root_, element, null); + + if(rslt) { + super.nNodes_++; + } + } + + } +} diff --git a/src/main/java/datastructs/adt/BinaryTree.java b/src/main/java/datastructs/adt/BinaryTree.java index 4fb376d..d951a97 100644 --- a/src/main/java/datastructs/adt/BinaryTree.java +++ b/src/main/java/datastructs/adt/BinaryTree.java @@ -16,13 +16,11 @@ public BinaryTree(ITreeInsertStrategy insertStrategy){ /** * Push a new element in the ADT */ - public final void push(E element){ + public void push(E element){ if(super.root_ == null){ - TreeNodeCreator creator = new TreeNodeCreator<>(); - super.root_ = creator.create(element, null, 0, 2); - super.nNodes_++; + this.createRoot(element); } else { @@ -40,6 +38,19 @@ public boolean satisfies(TreeNode data) { } + /** + * Create the root element + * @param element + */ + protected void createRoot(E element){ + + TreeNodeCreator creator = new TreeNodeCreator<>(); + super.root_ = creator.create(element, null, 0, 2); + super.nNodes_++; + } + + + /** * Recursively add the element at the first null entry that is diff --git a/src/main/java/utils/BSTInsertStratergy.java b/src/main/java/utils/BSTInsertStratergy.java new file mode 100644 index 0000000..2a13c00 --- /dev/null +++ b/src/main/java/utils/BSTInsertStratergy.java @@ -0,0 +1,49 @@ +package utils; + +import java.util.Comparator; + +/** + * + */ +public class BSTInsertStratergy implements ITreeInsertStrategy { + + + /** + * Constructor + */ + public BSTInsertStratergy(Comparator comparator){ + this.comparator = comparator; + } + + /** + * Insert a new node with the given data in the tree having the given root which has the given parent + * The insertion position is meant to satisfy the given predicate. It returns to + * the calling site the newly created node + */ + public boolean insert(TreeNode root, TreeNode parent, E data, + IPredicate> insertPosPredicate){ + + if(comparator.compare(data, parent.getData()) == 1){ + + parent.setChild(1 , new TreeNode<>(data, parent, 2)); + return true; + } + else if(comparator.compare(data, parent.getData() ) == -1){ + parent.setChild(0 , new TreeNode<>(data, parent, 2)); + return true; + } + + return false; + } + + /** + * Returns the type of the insert + */ + public TreeInsertMethod type(){return TreeInsertMethod.BST; } + + + /** + * The object used for comparisons + */ + Comparator comparator; +} diff --git a/src/main/java/utils/DfsInsertStrategy.java b/src/main/java/utils/DfsInsertStrategy.java index 4b7ae62..e17f833 100644 --- a/src/main/java/utils/DfsInsertStrategy.java +++ b/src/main/java/utils/DfsInsertStrategy.java @@ -2,13 +2,13 @@ -public class DfsInsertStrategy implements ITreeInsertStrategy { +public class DfsInsertStrategy implements ITreeInsertStrategy { @Override public final TreeInsertMethod type(){return TreeInsertMethod.DFS; } @Override - public final boolean insert(TreeNode root, TreeNode parent, DataTp data, IPredicate> insertPosPredicate){ + public final boolean insert(TreeNode root, TreeNode parent, E data, IPredicate> insertPosPredicate){ return doInsert(root, parent, data, insertPosPredicate).first; } diff --git a/src/main/java/utils/ITreeInsertStrategy.java b/src/main/java/utils/ITreeInsertStrategy.java index aa86203..66cb402 100644 --- a/src/main/java/utils/ITreeInsertStrategy.java +++ b/src/main/java/utils/ITreeInsertStrategy.java @@ -3,14 +3,14 @@ /** * Insertion strategy for trees */ -public interface ITreeInsertStrategy { +public interface ITreeInsertStrategy { /** * Insert a new node with the given data in the tree having the given root which has the given parent * The insertion position is meant to satisfy the given predicate. It returns to * the calling site the newly created node */ - boolean insert(TreeNode root, TreeNode parent, DataTp data, IPredicate> insertPosPredicate); + boolean insert(TreeNode root, TreeNode parent, E data, IPredicate> insertPosPredicate); /** * Returns the type of the insert diff --git a/src/main/java/utils/TreeInsertMethod.java b/src/main/java/utils/TreeInsertMethod.java index 9e778cb..b22b674 100644 --- a/src/main/java/utils/TreeInsertMethod.java +++ b/src/main/java/utils/TreeInsertMethod.java @@ -2,5 +2,5 @@ public enum TreeInsertMethod { - DFS, BFS + DFS, BFS, BST, INVALID } diff --git a/src/main/java/utils/TreeNode.java b/src/main/java/utils/TreeNode.java index d016678..f4a3c85 100644 --- a/src/main/java/utils/TreeNode.java +++ b/src/main/java/utils/TreeNode.java @@ -29,12 +29,41 @@ public TreeNode(E data, TreeNode parent, int level, int nChildren){ } } + + /** + * Create a node with the specified data and the given father + */ + public TreeNode(E data, TreeNode parent, int nChildren){ + + this.data_ = data; + this.parent_ = parent; + this.level_ = 0; + + if(parent != null){ + this.level_ = parent.getLevel() + 1; + } + + if(nChildren >=1) { + this.children_ = new ArrayList>(nChildren); + } + + for(int c=0; c < nChildren; ++c){ + this.children_.add(null); + } + } + /** * Set the data of the node */ public final void setData(E data){this.data_ = data;} + /** + * Returns the data stored by the node + */ + public final E getData(){return this.data_; } + + /** * Return the number of children the node has */ diff --git a/src/test/java/datastructs/adt/BinarySearchTreeRunner.java b/src/test/java/datastructs/adt/BinarySearchTreeRunner.java new file mode 100644 index 0000000..bd3383d --- /dev/null +++ b/src/test/java/datastructs/adt/BinarySearchTreeRunner.java @@ -0,0 +1,35 @@ +package datastructs.adt; + +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +public class BinarySearchTreeRunner { + + public static void run(String[] args){ + + System.out.println("============================"); + System.out.println("Start executing BinarySearchTree tests"); + + Result result = JUnitCore.runClasses(BinarySearchTreeTest.class); + + if( !result.wasSuccessful()) { + for (Failure failure : result.getFailures()) { + System.out.println(failure.toString()); + } + } + else{ + System.out.println("\tAll tests passed: "+ result.getRunCount()); + } + + System.out.println("\tTest run time: "+ result.getRunTime()); + System.out.println("Done...."); + System.out.println("============================"); + + } + + public static void main(String[] args) { + + BinarySearchTreeRunner.run(args); + } +} diff --git a/src/test/java/datastructs/adt/BinarySearchTreeTest.java b/src/test/java/datastructs/adt/BinarySearchTreeTest.java new file mode 100644 index 0000000..897413b --- /dev/null +++ b/src/test/java/datastructs/adt/BinarySearchTreeTest.java @@ -0,0 +1,49 @@ +package datastructs.adt; + +import org.junit.Test; +import utils.TreeNode; + +import java.util.Comparator; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class BinarySearchTreeTest { + + + /** + * Test Scenario: Application creates BST and attempts to insert an item larger than the root + * Exepected Output: Item should be properly insert at the right subtree of the root + */ + @Test + public final void testPushLargerThanRoot(){ + + Comparator comparator = (Integer a, Integer b)->{ + if( a.equals(b)){ + return 0; + } + else if( a.intValue() > b.intValue()){ + return 1; + } + + return -1; + }; + + BinarySearchTree tree = new BinarySearchTree<>(comparator); + + // insert an item + tree.push(10); + + TreeNode root = tree.getRoot(); + assertEquals("Invalid tree size", tree.size(), 1); + assertNotNull("Root node is null", root); + + // this should be inserted at the right sub tree + tree.push(15); + + assertEquals("Invalid tree size", tree.size(), 2); + + TreeNode rChild = root.getChild(1); + assertNotNull("Right child node is null", rChild); + assertEquals("Invalid right child data", rChild.getData().intValue(), 15); + } +}