Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Computing rank of a node in a binary search tree

If each node in a binary search tree stores its weight (number of nodes in its subtree), what would be an efficient method to compute a rank of a given node (its index in the sorted list) as I search for it in the tree?

like image 708
dissem Avatar asked Sep 28 '14 01:09

dissem


2 Answers

Start the rank at zero. As the binary search proceeds down from the root, add the sizes of all the left subtrees that the search skips by, including the left subtree of the found node.

I.e., when the search goes left (from parent to left child), it discovers no new values less than the searched item, so the rank stays the same. When it goes right, the parent plus all the nodes in the left subtree are less than the searched item, so add one plus the left subtree size. When it finds the searched item. any items in the left subtree of the node containing the item are less than it, so add this to the rank.

Putting this all together:

int rank_of(NODE *tree, int val) {
  int rank = 0;
  while (tree) {
    if (val < tree->val) // move to left subtree
      tree = tree->left;
    else if (val > tree->val) {
      rank += 1 + size(tree->left);
      tree = tree->right;
    }
    else 
      return rank + size(tree->left);
  }
  return NOT_FOUND; // not found
}

This returns the zero-based rank. If you need 1-based then initialize rank to 1 instead of 0.

like image 194
Gene Avatar answered Nov 16 '22 05:11

Gene


Since each node has a field storing its weight, the first you should implement a method call size() which return the number of nodes in a node's substree:

private int size(Node x)
{
if (x == null) return 0;
else return x.N;
} 

then compute the rank of a given node is easy

public int rank(Node key)
{ return rank(key,root) }

    private int rank(Node key,Node root)
    {
        if root == null 
             return 0;
        int cmp = key.compareTo(root);
// key are smaller than root, then the rank in the whole tree
// is equal to the rank in the left subtree of the root.
        if (cmp < 0) {
            return rank(key, root.left) 
        } 
//key are bigger than root,the the rank in the whole tree is equal
// to the size of subtree of the root plus 1 (the root) plus the rank 
//in the right sub tree of the root.
        else if(cmp > 0){
            return size(root.left) + 1 + rank(key,root.right); 
        } 
// key equals to the root, the rank is the size of left subtree of the root
        else return size( root.left);  
    }
like image 23
Jade Tang Avatar answered Nov 16 '22 06:11

Jade Tang