In: Computer Science
import java.util.ArrayList;
/*
Lab-08: BinarySearchTree Implementation
Rules:
1. Allow Tester to iterate
through all nodes using the in-order traversal as the
default.
This
means, in Tester the following code should work for an instance of
this class
called bst
that is storing Student objects for the data:
BinarySearchTree_Lab08<String> bst = new
BinarySearchTree_Lab08<String>();
bst.add("Man");
bst.add("Soda"); bst.add("Flag");
bst.add("Home");
bst.add("Today"); bst.add("Jack");
for(String s : bst)
System.out.println(s);
2. You can not
use a size variable to keep track of the number of nodes
*/
/**
* Lab-08: BinarySearchTree Implementation
*
* @author
*
*/
public class BinarySearchTree_Lab08<T> {
//======================================================================================
Properties
private Node root;
//======================================================================================
Constructors
public BinarySearchTree_Lab08() {
}
// Constructor that takes an array of items and
populates the tree
public BinarySearchTree_Lab08(T[] items) {
}
//======================================================================================
Methods
public void add(T data) { // Implement
recursively and do NOT allow duplicates
}
// Returns the traversal of this tree as an
array
public ArrayList<T> preOrder_Traversal()
{
ArrayList<T> data = new
ArrayList<T>();
preOrder_Traversal(root,
data);
return data;
}
private void preOrder_Traversal(Node n,
ArrayList<T> data) {
}
public ArrayList<T> inOrder_Traversal()
{
ArrayList<T> data = new
ArrayList<T>();
inOrder_Traversal(root,
data);
return data;
}
private void inOrder_Traversal(Node n,
ArrayList<T> data) {
}
public ArrayList<T> postOrder_Traversal()
{
ArrayList<T> data = new
ArrayList<T>();
postOrder_Traversal(root,
data);
return data;
}
private void postOrder_Traversal(Node n,
ArrayList<T> data) {
}
public ArrayList<T> breadthFirst_Traversal()
{
return null;
}
// Since this is a binary SEARCH tree, you should
write
// an efficient solution to this that takes advantage
of the order
// of the nodes in a BST. Your algorithm should be, on
average,
// O(h) where h is the height of the BST.
public boolean contains(T data) {
return false;
}
// returns the smallest value in the tree
// or throws an IllegalStateException() if the
// tree is empty. Write the recursive version
public T min() { return min(root); }
// this method is done for you.
private T min(Node n) { // Write this
method.
return null;
}
// returns the largest value in the tree
// or throws an IllegalStateException() if the
// tree is empty. Write the recursive version
public T max() { return max(root); }
// this method is done for you.
private T max(Node n) { // Write this
method.
return null;
}
// Returns whether the tree is empty
public boolean isEmpty() {
return false;
}
// returns the height of this BST. If a BST is
empty, then
// consider its height to be -1.
public int getHeight() {
return -1;
}
// returns the largest value of all the leaves
// If the tree is empty, throw an
IllegalStateException()
// Note, this is different than max as this is the
max
// of all leaf nodes
public T maxLeaf() {
return null;
}
// counts the number of nodes in this BST
public int nodeCount() {
return -1;
}
// returns the "level" of the value in a
tree.
// the root is considered level 0
// the children of the root are level 1
// the children of the children of the root are level
2
// and so on. If a value does not appear in the tree,
return -1
// 15
// / \
// 10 28
// \ \
// 12 40
// /
// 30
// In the tree above:
// getLevel(15) would return 0
// getLevel(10) would return 1
// getLevel(30) would return 3
// getLevel(8) would return -1
public int getLevel(T n) {
return -1;
}
// A tree is height-balanced if at each node, the
heights
// of the node's two subtrees differs by no more than
1.
// Special note about null subtrees:
// 10
// \
// 20
// Notice in this example that 10's left subtree is
null,
// and its right subtree has height 0. We would
consider this
// to be a balanced tree. If the tree is empty, return
true;
public boolean isBalanced() {
return false;
}
//======================================================================================
Inner Node Class
private class Node {
private T data;
private Node left, right;
private Node(T data) {
this.data =
data;
left = right =
null;
}
}
}
/**
* This file contains an implementation of a Binary Search Tree (BST) Any comparable data is allowed
* within this tree (numbers, strings, comparable Objects, etc...). Supported operations include
* adding, height,isBalanced and containment checks. Furthermore, multiple tree traversal Iterators
* are provided including: 1) Preorder traversal 2) Inorder traversal 3) Postorder traversal 4)
* BFS traversal
*
*/
import java.util.ArrayList;
class BinarySearchTree_Lab08<T extends Comparable<T>> {
public BinarySearchTree_Lab08() {
}
// Constructor that takes an array of items and populates the tree
public BinarySearchTree_Lab08(T[] items) {
for(T item : items) {
add(item);
}
}
// Tracks the number of nodes in this BST
private int nodeCount = 0;
// This BST is a rooted tree so we maintain a handle on the root node
private Node root = null;
// Internal node containing node references
// and the actual node data
private class Node {
T data;
Node left, right;
public Node(Node left, Node right, T elem) {
this.data = elem;
this.left = left;
this.right = right;
}
}
// Check if this binary tree is empty
public int isEmpty() {
return nodeCount() == 0 ? nodeCount() : -1;
}
// Get the number of nodes in this binary tree
public int nodeCount() {
return nodeCount;
}
// Add an element to this binary tree. Returns true
// if we successfully perform an insertion
public boolean add(T elem) {
// Check if the value already exists in this
// binary tree, if it does ignore adding it
if (contains(elem)) {
return false;
// Otherwise add this element to the binary tree
} else {
root = add(root, elem);
nodeCount++;
return true;
}
}
// Private method to recursively add a value in the binary tree
private Node add(Node node, T elem) {
// Base case: found a leaf node
if (node == null) {
node = new Node(null, null, elem);
} else {
// Pick a subtree to insert element
if (elem.compareTo(node.data) < 0) {
node.left = add(node.left, elem);
} else {
node.right = add(node.right, elem);
}
}
return node;
}
// Helper method to find the leftmost node (which has the smallest value)
private Node findMin(Node node) {
while (node.left != null) node = node.left;
return node;
}
//return the min node
public T findMin() {
Node node = findMin(root);
return node.data;
}
// Helper method to find the rightmost node (which has the largest value)
private Node findMax(Node node) {
while (node.right != null) node = node.right;
return node;
}
//return the max node
public T findMax() {
Node node = findMax(root);
return node.data;
}
// returns true is the element exists in the tree
public boolean contains(T elem) {
return contains(root, elem);
}
// private recursive method to find an element in the tree
private boolean contains(Node node, T elem) {
// Base case: reached bottom, value not found
if (node == null) return false;
int cmp = elem.compareTo(node.data);
// Dig into the left subtree because the value we're
// looking for is smaller than the current value
if (cmp < 0) return contains(node.left, elem);
// Dig into the right subtree because the value we're
// looking for is greater than the current value
else if (cmp > 0) return contains(node.right, elem);
// We found the value we were looking for
else return true;
}
// Computes the height of the tree, O(n)
public int height() {
return height(root);
}
// Recursive helper method to compute the height of the tree
private int height(Node node) {
if (node == null) return 0;
return Math.max(height(node.left), height(node.right)) + 1;
}
/* Helper function for getLevel().
It returns level of the data if data is
present in tree, otherwise returns 0.*/
private int getLevelUtil(Node node,T data, int level)
{
if (node == null)
return 0;
if (node.data == data)
return level;
int downlevel = getLevelUtil(node.left,data,level + 1);
if (downlevel != 0)
return downlevel;
downlevel = getLevelUtil(node.right,data,level + 1);
return downlevel;
}
/* Returns level of given data value */
public int getLevel(T data)
{
if( contains(data) ){
return getLevelUtil(root, data, 1);
}
return -1;
}
// Helper method to find the max value leaf node (which has the largest value)
private Node maxLeaf(Node node) {
while (node.right != null) node = node.right;
return node;
}
//return the max leaf node
public T maxLeaf() {
Node node = maxLeaf(root);
return node.data;
}
// Helper method to find the tree is height balanced or not
private boolean isBalancedUtil(Node node)
{
int lh; /* for height of left subtree */
int rh; /* for height of right subtree */
/* If tree is empty then return true */
if (node == null)
return true;
/* Get the height of left and right sub trees */
lh = height(node.left);
rh = height(node.right);
if (Math.abs(lh - rh) <= 1
&& isBalancedUtil(node.left)
&& isBalancedUtil(node.right))
return true;
/* If we reach here then tree is not height-balanced */
return false;
}
/* Returns true if binary tree with root as root is height-balanced */
public boolean isBalanced()
{
return isBalancedUtil(root);
}
/* Given a binary tree, get its nodes according to the
"bottom-up" postorder traversal. */
private void postOrder_Traversal(Node node,ArrayList<T> data)
{
if (node == null)
return;
// first recur on left subtree
postOrder_Traversal(node.left,data);
// then recur on right subtree
postOrder_Traversal(node.right,data);
// now add data to array
data.add(node.data);
}
/* Given a binary tree, get its nodes in inorder*/
private void inOrder_Traversal(Node node,ArrayList<T> data)
{
if (node == null)
return;
/* first recur on left child */
inOrder_Traversal(node.left,data);
/* then add data to array */
data.add(node.data);
/* now recur on right child */
inOrder_Traversal(node.right,data);
}
/* Given a binary tree, get its nodes in preorder*/
private void preOrder_Traversal(Node node,ArrayList<T> data)
{
if (node == null)
return;
/* first add data to array */
data.add(node.data);
/* then recur on left sutree */
preOrder_Traversal(node.left,data);
/* now recur on right subtree */
preOrder_Traversal(node.right,data);
}
/* Helper Function to Get nodes at the BFS Order */
private void breadthFirst_TraversalUtil(Node node,int level,ArrayList<T> data)
{
if (node == null)
return;
if (level == 1)
data.add(node.data);
else if (level > 1)
{
breadthFirst_TraversalUtil(node.left, level-1,data);
breadthFirst_TraversalUtil(node.right, level-1,data);
}
}
/* function to get BFS order traversal of tree*/
private void breadthFirst_Traversal(Node node,ArrayList<T> data)
{
int h = height();
int i;
for (i=1; i<=h; i++)
breadthFirst_TraversalUtil(root, i,data);
}
// Returns the traversal of this tree as an array
// Pre Order Traversal
public ArrayList<T> preOrder_Traversal() {
ArrayList<T> data = new ArrayList<T>();
preOrder_Traversal(root, data);
return data;
}
// In Order Traversal
public ArrayList<T> inOrder_Traversal() {
ArrayList<T> data = new ArrayList<T>();
inOrder_Traversal(root, data);
return data;
}
// Post Order Traversal
public ArrayList<T> postOrder_Traversal() {
ArrayList<T> data = new ArrayList<T>();
postOrder_Traversal(root, data);
return data;
}
// BFS Search Order
public ArrayList<T> breadthFirst_Traversal() {
ArrayList<T> data = new ArrayList<T>();
breadthFirst_Traversal(root,data);
return data;
}
}
public class Main{
public static void main(String args[]){
//Creating Object Without Constructor Parameters
BinarySearchTree_Lab08<Integer> tree = new BinarySearchTree_Lab08<Integer>();
System.out.println("Initialize Tree Values Without Using Constructor: ");
tree.add(1);
tree.add(2);
tree.add(3);
tree.add(4);
tree.add(5);
ArrayList<Integer> data = new ArrayList<Integer>();
//Pre Order Traversal
System.out.print("Pre Order Traversal: ");
data = tree.preOrder_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
//In Order Traversal
System.out.println("");
System.out.print("In Order Traversal: ");
data = tree.inOrder_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
//Post Order Traversal
System.out.println("");
System.out.print("Post Order Traversal: ");
data = tree.postOrder_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
//BFS Order Traversal
System.out.println("");
System.out.print("BFS Order Traversal: ");
data = tree.breadthFirst_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
System.out.println("");
//Creating Object Using Constructor Parameters
BinarySearchTree_Lab08<Integer> tree1 = new BinarySearchTree_Lab08<Integer>(new Integer[] {1,2,3,4,5});
System.out.println("Initialize Tree Values Using Constructor: ");
//Pre Order Traversal
System.out.print("Pre Order Traversal: ");
data = tree1.preOrder_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
//In Order Traversal
System.out.println("");
System.out.print("In Order Traversal: ");
data = tree1.inOrder_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
//Post Order Traversal
System.out.println("");
System.out.print("Post Order Traversal: ");
data = tree1.postOrder_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
//BFS Order Traversal
System.out.println("");
System.out.print("BFS Order Traversal: ");
data = tree1.breadthFirst_Traversal();
for (int i = 0; i < data.size(); i++){
System.out.print(data.get(i) + " ");
}
}
}
Output: