Notes for July 27, 2005

Debugging

Debugging is a skill that you have to learn to be a successful programmer. It is imperative that you use System.out.println() to print out variables in your code to make sure that they are what you expect them to be. For example, if you want to check for the value of a String, use something like:
    System.out.println("token = (" + token + ")");
The parenthesis will tell if you the variable token has spaces in it by marking the exact start and end of the variable.

Additionally, you can use assertions to ensure that certain properties hold in your code at certain points. I created a class called Assert with some methods you can use to help in your debugging.

    public static void assertTrue(boolean test, int expected, int actual) {
        if (!test) {
            System.out.println("value = (" + expected + "/" + actual + ")");
            assertTrue(test);
        }
    }
The reason the method is called assertTrue and not just assert is because Java already has an assertion mechanism (assert is a Java keyword), but activating it requires playing with compiler flags. It's a lot simpler to include Assert.java in your directory and compile it along with everything else. An example of how you would use it:
    Assert.assertTrue(q.size() == 10, 10, q.size());
If the size of q is not 10, then your program will first print out what it expected to see and what it actually found and then crash at that point and a stack trace will appear showing you on exactly what line your program broke.

You should feel free to add other methods that will suit your needs.

lookup

lookup traverses the tree and returns true if it finds a match, otherwise it returns false. This code is very similar to hasValue, except instead of recursing on both branches, it can recurse on a single branch, because of the way binary search trees are constructed. If the query is not in the tree, hasValue has to search the whole tree and that will take O(n) time in the worst case. lookup will take O(length of the longest path). If the tree is balanced (like TreeMap), this will be O(log n).
    public boolean lookup(Object query) {
        return lookup(root, query);
    }

    private boolean lookup(SearchTreeNode node, Object query) {
        if (node == null) {
	    return false;
	} else if (node.data.compareTo(query) == 0) {
	    return true;
	} else if (node.data.compareTo(query) < 0) {
	    return lookup(node.right, query);
	} else {
	    return lookup(node.left, query);
	}
    }

insert

The following version of insert is faulty. It differs from the version of insert in the handout. Why won't it work? We'll revisit this question later.
    public void insert(Object next) {
        insert(next, root);
    }

    private void insert(Object next, SearchTreeNode node) {
        if (node == null) {
	    node = new SearchTreeNode(next);
	} else if (node.data.compareTo(next) < 0) {
	    insert(next, node.right);
	} else { // compareTo >= 0
	    insert(next, node.left);
	}
    }