1
\$\begingroup\$

I have written a code of Binary Search tree that extends comparable and implements an interface. The code for leaves and the helper method countLeaves, makes sure that all of the test goes through except for one, heightIsLogOfNumLeavesTreeIsPerfect().

// TODO: Look at the Leaves and helper method in the tree class and see how I should change it so that this test goes through aswell.

//EDIT: Added the whole testclass

I have also included the message i get when the test does not go through and the test in the test class

java.lang.AssertionError: 
Expected: <2>
     but: was <0>
Expected :<2>
Actual   :<0>

import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.Timeout;
import static org.junit.Assert.*;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
import java.util.stream.IntStream;
/**
 * Test class for a tree.
 *
 * @author Melissa Saber Tehrani
 * @version 2022-02-12
 */
public class TreeTest{
    @Rule public Timeout globalTimeout = Timeout.seconds(5);

    Tree<Integer> tree;
    int[] elementsInTree;
    int[] elementsNotInTree;

    @Before
    public void setUp() {
        /**
         * This tree should look like this:
         *
         *               8
         *             /  \
         *            3   10
         *           / \    \
         *          1   6    14
         *             / \   /
         *            4   7 13
         */
        tree = new Tree<>();
        elementsInTree = new int[] {8, 10, 14, 13, 3, 1, 6, 4, 7};
        for (int elem : elementsInTree) {
            tree.insert(elem);
        }
        elementsNotInTree = new int[] {34, -3, -10, 12, 74, 5};
    }

    // Tests for height
    @Test
    public void heightIsZeroWhenTreeIsEmpty() {
        // Arrange
        Tree<Integer> emptyTree = new Tree<>();
        // Act
        int height = emptyTree.height();
        // Assert
        assertThat(height, equalTo(0));
    }

    @Test
    public void heightIsZeroWhenTreeHasOnlyRoot() {
        // Arrange
        Tree<Integer> rootOnlyTree = new Tree<>();
        rootOnlyTree.insert(1338);
        // Act
        int height = rootOnlyTree.height();
        // Assert
        assertThat(height, equalTo(0));
    }

    @Test
    public void heightIsLogOfNumLeavesTreeIsPerfect() {
        // For a perfect tree, tree.height() == log2(tree.leaves()

        // Arrange
        Tree<Integer> tree = new Tree<>();
        int[] elements = new int[] {8, 3, 10, 1, 6, 9, 14};
        int numLeaves = 4;
        int logNumLeaves = (int) Math.round(Math.log(numLeaves) / Math.log(2));
        for (int elem : elements) {
            tree.insert(elem);
        }

        // Act
        int height = tree.height();
        // Assert
        assertThat(height, equalTo(logNumLeaves));
    }
}

/**
 * An interface describing a generic Comparable
 */

public interface BSTInterface <T>{

    boolean search(T elem);
   
    boolean insert(T elem);

        int size();

    int height();
   
    int leaves();
}
/**
 * An Binary Search tree implementation of the comparable interface.
 * @param <T>
 */
public class Tree <T extends Comparable <T>> implements BSTInterface <T>{
    private int size;
    private Node root;
    public class Node{
        private Node Left;
        private Node Right;
        private T data;

        public Node(T data){
            this.data = data;
        }
        public Node getRight(){
            return Right;
        }

        public Node getLeft() {
            return Left;
        }

        public T getData() {
            return data;
        }
    }
    public Tree (){
        size = 0;
        root = null;
    }


    /**
     * Test for presence of a value.
     * @param elem
     * @return true/false
     */
    @Override
    public boolean search(T elem) {
        if(root == null ||elem == null){
        return false;
        }
        Node node = root;
        while(true){
            if(node.data.compareTo(elem) > 0){
                if(node.Right == null){
                    return false;
                } else{
                    node = node.Right;
                }
            } else if(node.data.compareTo(elem) == 0){
                break;
            } else{
                if(node.Left== null){
                    return false;
                }
                else{
                    node = node.Left;
                }
            }
        }
        return true;
    }

    /**
     * Add value to tree; duplicates are not allowed.
     * Return true if the element is not already present (and is thus inserted),
     * false otherwise.
     *
     * @param elem
     * @return true/false
     */
    @Override
    public boolean insert(T elem) {
        if (elem == null){
            return false;
        }
        if (root == null){
            root = new Node(elem);
            size++;
            return true;
        }
        Node node = root;
        while (true){
            if (node.data.compareTo(elem) > 0) {
                if (node.Right == null){
                    node.Right = new Node(elem);
                    size++;
                    break;
                } else {
                    node = node.Right;
                }

            } else if (node.data.compareTo(elem) == 0) {
                return false;
            } else {
                if (node.Left == null){
                    node.Left = new Node(elem);
                    size++;
                    break;
                } else {
                    node = node.Left;
                }
            }
        }
        return true;
    }


    /**
     * the number of elements in the tree
     * @return size.
     */
    @Override
    public int size() {
        return size;
    }

    /**
     * The height of the tree.
     * The empty tree and the tree with only the root node both have height 0.
     * @return the height of the tree.
     */
    @Override
    public int height() {
        return countHeight(root);
    }
    /**
     * Helper method for height
     */
    private int countHeight(Node node){
        if(node == null) {
            return 0;
        }
        int rightHeight = countHeight(node.Right);
        int leftHeight = countHeight(node.Left);;
        int height = Math.max(leftHeight, rightHeight);
        return height;
    }

    /**
     * The number of leaves in the tree.
     * @return the amount of leaves the tree have.
     */
    @Override
    public int leaves() {
        return countLeaves(root);
    }
    /**
     * Helper method for leaves
     */
    private int countLeaves(Node node) {
        if (node == null) {
            return 0;
        }
        if (node.Right == null && node.Left == null) {
            return 1;
        }
        int count = 0;
        count += countLeaves(node.Left);
        count += countLeaves(node.Right);
        return count;
    }

    /**
     * A string describing the tree
     * @return
     */
    public String toString(){
        String str = "[" + helpToString(root);
        if (str.length() > 1) {
            str = str.substring(0, str.length() - 2);
        } return str + "]";
    }

    /**
     * Helper method for toString
     */
    private String helpToString(Node node) {
        String str = "";
        if (node != null) {
            str += helpToString(node.Right);
            str += node.data + ", ";
            str += helpToString(node.Left);
        }
        return str;
      }
}
\$\endgroup\$
2
  • \$\begingroup\$ I think we need to agree on terminology. How do you define the height of a BST? Take the deepest BST node, call it D. Now, is the height of a BST: (1) the number of edges on a path from the root node to D, or (2) is it the number of nodes on a path from the root node to D? \$\endgroup\$ Commented Feb 12, 2022 at 8:50
  • 1
    \$\begingroup\$ So my question boils down to this one: if the BST contains only root node, is its height 0 or 1? \$\endgroup\$ Commented Feb 12, 2022 at 8:51

1 Answer 1

-1
\$\begingroup\$

Advice 1

int logNumLeaves = (int) Math.round(Math.log(numLeaves) / Math.log(2));
  1. The above formula assumes that the tree is balanced. Your implementation (and a test tree) is not.
  2. Not sure about the math part.

Advice 2

public int height() {
    return countHeight(root);
}

private int countHeight(Node node){
    if(node == null) {
        return 0;
    }
    int rightHeight = countHeight(node.Right);
    int leftHeight = countHeight(node.Left);;
    int height = Math.max(leftHeight, rightHeight);
    return height;
}

Will always return 0. You need instead:

public int height() {
    return countHeight(root);
}

private int countHeight(Node<E> node) {
    if (node == null) {
        return 0;
    }

    return 1 + Math.max(countHeight(node.getLeftChild()),
                        countHeight(node.getRightChild()));
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ if I write like that the test does still not work and another test does not work. heightIsLogOfNumLeavesTreeIsPerfect() gives a message Expected: <2> but: was <3> heightIsZeroWhenTreeHasOnlyRoot() gives a message Expected: <0> but: was <1> \$\endgroup\$ Commented Feb 12, 2022 at 7:54
  • \$\begingroup\$ @user17024023 Fair enough. Could you pleae supply the entire unit test file containing heightIsZeroWhenTreeHasOnlyRoot, etc.? \$\endgroup\$ Commented Feb 12, 2022 at 7:56
  • \$\begingroup\$ I have added the testclass, but I think I have solved it. When private int countHeight(Node node){ if(node == null) { return 0; } if (node.Left == null && node.Right == null) { return 0; } return 1 + Math.max(countHeight(node.getLeft()), countHeight(node.getRight())); } both test goes through \$\endgroup\$ Commented Feb 12, 2022 at 8:19

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.