0

Forgive me if this has been asked, but I wasn't able to find it while searching.. All of the search results were about traversing through the binary tree as if one was searching for a specific node - thus it would end up going down either left or right and so on.

But what about traversing through to update the size of the tree? Like say you've added a new node at the bottom, you'd have to then update the size of each node to reflect the new tree size.

Let's say this is the original tree and you add Z:

    D              D
   / \            / \
  A   S   -->    A   S
     /              / \
    N              N   Z
(size = 4)      (size = 5)

So to update the size, unless I'm thinking wrong, you'd have to update the node below first before you can update the one above it. Right? (To update D, you'd have to update S and A first)

So, how would you traverse from root to bottom but update from bottom up?

  • What you want to do isn't terribly difficult, but I'm wondering why you want to do it. Why do you have to traverse the whole tree to update the size? Is this a simplified example or are you storing the tree size in each node (and if so, why)? Why must you update the child nodes before their parents? – jerry Apr 09 '14 at 00:10
  • I was just wondering. Because I was randomly thinking about non-recursive insertion. After inserting a new node you'd have to somehow traverse through the tree again to update the size of each node (not the entire tree but just the side that got the new node). As for why update the child first, well my reasoning is this: size of S is 3 right? Because it depends on the size of its left and right child nodes and if each node is 1 then sizeOfS = 1 + size(s.left) + size(s.right). Or am I just overcomplicating this concept..? haha –  Apr 09 '14 at 00:27

1 Answers1

0

I'm still not sure what your use case for storing the size of each subtree is, but it's easy to keep it updated during each insert without resorting to recursion. For the sake of simplicity, let's assume you start with the following definitions:

public static class BSTNode
{
    public BSTNode leftTree = null;
    public BSTNode rightTree = null;
    public int subtreeSize = 1;
    public int value;

    public BSTNode(int valToAdd){
        value = valToAdd;
    }
}

public static class BST
{
    public BSTNode root;

    //public void insert(int valToAdd)
}

In the implementation of insert, we'd start at the root and traverse the tree to find the appropriate place to add the new value. We can update each subtree's size as we go. A simple implementation might look like the following:

public void insert(int valToAdd)
{
    if(root == null){
        root = new BSTNode(valToAdd);
        return;
    }

    BSTNode parent = root;
    BSTNode current = root;
    while(current != null){
        parent = current;
        ++current.subtreeSize;
        if(valToAdd <= current.value){
            current = current.leftTree;
        }
        else{
            current = current.rightTree;                
        }
    }

    if(valToAdd <= parent.value){
        parent.leftTree = new BSTNode(valToAdd);
    }
    else{
        parent.rightTree = new BSTNode(valToAdd);
    }
}

There are cases where you want to update starting from the bottom, such as tracking subtree height (which may be used in rebalancing). Assume the BSTNode definition is now:

public static class BSTNode
{
    public BSTNode leftTree = null;
    public BSTNode rightTree = null;
    public int height = 0;
    public int value;

    public BSTNode(int valToAdd){
        value = valToAdd;
    }
}

In insert, use a Stack (or anything that can provide LIFO semantics) to store the ancestors of the newly inserted node. Modifying our previous simple example:

public void insert(int valToAdd)
{
    if(root == null){
        root = new BSTNode(valToAdd);
        return;
    }

    java.util.Stack<BSTNode> stack = new java.util.Stack<BSTNode>();

    BSTNode parent = root;
    BSTNode current = root;
    while(current != null){
        parent = current;
        stack.push(current);
        if(valToAdd <= current.value){
            current = current.leftTree;
        }
        else{
            current = current.rightTree;                
        }
    }

    if(valToAdd <= parent.value){
        parent.leftTree = new BSTNode(valToAdd);
    }
    else{
        parent.rightTree = new BSTNode(valToAdd);
    }

    int height = 1;
    while(!stack.isEmpty()){
        current = stack.pop();
        current.height = Math.max(height, current.height);
        ++height;
    }
}
jerry
  • 2,581
  • 1
  • 21
  • 32