简体   繁体   English

此Splay Tree范围总和是否有更快的实现方式?

[英]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. 为此,我实现了以下名为summation.函数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. ret是全局int变量,在调用summation函数之前将其初始化为0 The two parameters st & ed defines the range (inclusive). sted这两个参数定义了范围(含)。

The summation function works at a complexity of O(n). summation函数的工作复杂度为O(n)。 Can anyone suggest any faster implementation for this?? 任何人都可以为此建议任何更快的实现吗?

This is the splay tree implementation I did some time ago and tested against SPOJ evaluation system (written in C++) : 这是我前一段时间做的splay tree实现,并针对SPOJ评估系统(用C ++编写)进行了测试:

https://ideone.com/aQgEpF https://ideone.com/aQgEpF

This tree implementation supports what u are asking for (range sum in O(log(n)) . 此树实现支持您要的内容( O(log(n))范围和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. 此外,每个节点还包含一个字段sum ,它是其子树中所有键的总和。 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. sum字段是延迟计算的,并且仅在拆分操作期间(沿拆分线)中继,这不允许深入到不需要计算的级别中。

First, as a side-note, having summation not return anything, instead manipulating a global variable, is probably not such a great idea . 首先,作为一个附带说明, summation不返回任何东西,而是操纵一个全局变量, 可能不是一个好主意 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. 进一步思考,您将看到如何使用此元数据回答范围查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM