Count number of smaller values while inserting into binary search tree (BST)
Asked Answered
H

1

3

I'm currently implementing an algorithm in which I need to know how many numbers, from the ones that have already been read, are smaller than the one that's currently being processed.

A way to do that is through merge sort, but I'm more interested in a BST approach.

This procedure is meant to compute in O(log n) the number of nodes with value less than the key node's value :

countLessThan(int x, node T)
    if T = null
        return
    if T.value >= x
        countLessThan(x, T.left) // T.left contains only numbers < T.value and T.right only numbers > T.value
    else
        globalResult += T.numLeft
        countLessThan(x, T.right)

The numLeft field in this case would be stored in each node and represent the number of nodes in its left subtree (itself included).

So my question is, how to update this particular field in a fast way?

Hedger answered 16/8, 2016 at 21:59 Comment(3)
You could update the numLeft value of every node you pass through when you're searching where to insert every new value into the tree; then you could read it out immediately.Camarena
Yup, I got to the same idea eventually. Can you post this as an answer in order to close the question?Hedger
I think, use Heap Tree.Suk
R
3

You could store the number of leaves connected to the left (less-than) side in every node, and increment this count for every branch you pass on the left when inserting a new leaf.

The number of values smaller than the newly inserted value can be calculated at the same time, by adding all the counts of the branches you pass on the right while inserting.

Below is a JavaScript code snippet to demonstrate the method:

function CountTree() {                           // tree constructor
    this.root = null;

    this.insert = function(value) {
        var branch = null, node = this.root, count = 0, after;
        while (node != null) {                   // traverse tree to find position
            branch = node;
            after = value > node.value;          // compare to get direction
            if (after) {
                node = branch.right;             // pass on the right (greater)
                count += branch.count;           // add all nodes to the left of branch
            } else {
                node = branch.left;              // pass on the left (smaller or equal)
                ++branch.count;                  // increment branch's count
            }
        }                                        // attach new leaf
        if (branch == null) this.root = new Leaf(value);
        else if (after) branch.right = new Leaf(value);
        else branch.left = new Leaf(value);
        return count;
    }

    function Leaf(value) {                       // leaf constructor
        this.value = value;
        this.left = null;
        this.right = null;
        this.count = 1;
    }
}

var t = new CountTree(), v = [5, 3, 8, 2, 4, 7, 9, 1, 4, 7, 8];
for (var i in v) {
    document.write("Inserting " + v[i] + " (found " + t.insert(v[i]) + " smaller)<BR>");
}

This is the tree from the example in the code, when inserting the last element (the second value 8). Every node has the count of nodes to its left (including itself) printed underneath its right vertex. When inserting the second 8, you pass the nodes with value 5, 8 and 7; of these, 5 and 7 are passed on the right, and the sum of their counts is 6 + 2 = 8, so there are 8 values smaller that 8 in the tree: 1, 2, 3, 4, 4, 5, 7 and 7. The first node with value 8 is passed on the left, so its count will be incremented from 3 to 4.

inserting second 8 into example tree

Rieth answered 16/8, 2016 at 22:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.