jbsu32
jbsu32

Reputation: 1064

Is there any faster implementation for this Splay Tree range sum?

I have coded a splay tree. The nodes are represented like this.

struct Node{
    Node *l;  /// The left  Node
    Node *r;  /// The right Node
    int v;    /// The Value
};

Now, I need to know the summation of all the numbers in the tree within a certain range. For this, i implemented the following function named summation.

void summation(Node *R, int st, int ed)
{
    if(!R) return;
    if(R->v < st){        /// should not call left side
        summation(R->r, st, ed);
    }
    else if(R->v > ed){   /// should not call right side
        summation(R->l, st, ed);
    }
    else{                /// should call both side
        ret+=R->v;
        summation(R->l, st, ed);
        summation(R->r, st, ed);
    }
    return;
}

ret is a global int variable which is initialized to 0 before calling the summation function. The two parameters st & ed defines the range (inclusive).

The summation function works at a complexity of O(n). Can anyone suggest any faster implementation for this??

Upvotes: 4

Views: 1161

Answers (2)

Yerken
Yerken

Reputation: 1942

This is the splay tree implementation I did some time ago and tested against SPOJ evaluation system (written in C++) :

https://ideone.com/aQgEpF

This tree implementation supports what u are asking for (range sum in O(log(n)).

The key idea here is to use split and merge, to extract the subtree covering the range. Additionally each node contains a field sum, which is a sum of all keys in its subtree. The sum field is lazily evaluated and only relayed during split operation (along the splitting line), which allows not to go deeper into the levels not required to be calculated.

Upvotes: 4

Ami Tavory
Ami Tavory

Reputation: 76346

First, as a side-note, having summation not return anything, instead manipulating a global variable, is probably not such a great idea. You probably should consider omitting this global variable, and have the recursive function just return what it found (and have a call sum up the values returned by its further recursive calls, before returning this sum itself).

Regarding your specific question, you can optimize the summation operation by augmenting node metadata. This will reduce the summation operation's order of growth, without affecting the order of growth of the other operations. On the downside, this will somewhat reduce the speed of the other operations. It is up to you to decide if this tradeoff is good for you.

The basic idea is as follows:

  1. Keep within each node another field indicating the sum of the items in the tree rooted at this node.

  2. With some thought, you can see how to efficiently update this information when updating the tree.

  3. With some further thought you can see how you can answer a range query using this metadata.

Upvotes: 1

Related Questions