Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Balancing a binary search tree

Ok, I am trying to get a binary search tree to balance, and I know why it's not working, but I don't know how to fix it. This is what I have for my balancing methods.

    public void balance(){
    if(isEmpty()){
        System.out.println("Empty Tree");
        return;
    }
    if(!isEmpty()){
        values = new Object[count()];
        index = 0;
        createAscendingArray(root);
        clear();
        balanceRecursive(0, index);
                    values = null;
    }


}

private void createAscendingArray(TreeNode<E> current){
    if(current == null)
        return;
    if(current.getLeftNode() != null)
        createAscendingArray(current.getLeftNode());
    else if(current.getRightNode() != null)
        createAscendingArray(current.getRightNode());
    values[index] = current.getData();
    index++;


}

private void balanceRecursive(int low, int high){
    if(low == high)
        return;
    else if(low > high/2)
        balanceRecursive(high/2, high);
    else if(low < high/2)
        balanceRecursive(low, high/2);  

    E insert = (E) values[(low + high)/2];
    insertItem(insert);

}

To add some clarity, index is a predefined private int variable, values is also a predefined Object[]. Root is the node at the start of my unbalanced tree. First off, I know my array is adding the values in reverse order. Right now I'm just testing with 1, 2, 3, 4, 5, 6 being added to the tree, so then my array comes out with 654321. I'm not sure how I need to place the addition of the values to my array so that it will add them in the correct ascending instead of descending order.

Now when I look at my code, I know that the balanceRecursive() method is never going to work for implementing the top half of the array. My issue is I don't know how to write it so that it will. I am tasked to do this with recursion, which I am not very familiar with. I could do this with iteration, but it's strictly defined I must use recursion.

Balance is supposed to work like this: Algorithm for balance()

  • Check if tree is empty

o If it is, print “Empty Tree”

o Return

  • If tree is not Empty

o Create array of Objects the size of the Tree

o Set index to 0

o Populate the array with all values in ASCENDING order (createAscendingArray())

o Clear Tree

o Repopulate Tree from Object array (balanceRecursive())

o Set the values array to null

(I have methods written already for count() to count the number of nodes in my tree and clear() to empty the tree)

balanceRecursive() is supposed to do the following Repopulates the Tree with the values in the values data member. These must be added in the appropriate order to create a balanced tree.

  • Add the middle element

  • This creates two sub arrays, a left and a right

  • Add the middle of those sub arrays

  • This creates even more sub arrays

  • Keep adding middles of sub arrays until there are none

I know for this method I am never using the larger set of sub arrays and that's the part of the recursion that I can't figure out how to implement. Any suggestions on how to clean up my recursion?

EDIT:

I changed my createAscendingArray() to the following:

    private void createAscendingArray(TreeNode<E> current){

    if(current == null)
        return;
    createAscendingArray(current.getLeftNode());
    values[index] = current.getData();
    index++;
    createAscendingArray(current.getRightNode());



}

That should function like an inOrder traverse of the BST am I right?

like image 737
Neonjoe Avatar asked Dec 03 '13 01:12

Neonjoe


1 Answers

First, you don't need to copy the old tree. You can rebalance it in-place using the Stout-Warren algorithm, though admittedly that's a bit more complex than just reading out the old tree, clearing it and creating a new one.

But as to your actual question, the recursion function you want is

private void balanceRecursive(int low, int high){

    if(low == high)
        return;

    int midpoint = (low + high)/2;

    E insert = (E) values[midpoint];
    insertItem(insert);

    balanceRecursive(midpoint+1, high);
    balanceRecursive(low, midpoint);  
}

As an aside, don't use an array of objects for values, use a List<E> so you don't need to cast to type E when you read out of it.

like image 133
Andy Jones Avatar answered Sep 28 '22 07:09

Andy Jones