我正在尝试搜索AST(抽象语法树)中的特定节点。基本思路是:
问题:在AST中搜索这50个项目的最佳方法是什么?
现在,我正在考虑使用包含这50个项目的Arraylist。然后,遍历AST并使用循环将每个节点与Arraylist进行比较。从表现来看这是个好主意吗?我希望快速完成操作。还有其他方法可以解决这个问题吗?
答案 0 :(得分:0)
我不会使用Arralylist,因为它需要您每次都扫描它,这只是开销。您可以轻松地将50个谓词写为“p1或p2或....”。
您可以搜索树一次,应用50个谓词来决定是否有一个有趣的节点,或者搜索树50次,在每个单独的传递上应用一个谓词。在这两种情况下,您都必须运行谓词,因此它们不会以任何方式更改成本(请注意下面)。
如果你搜索一次,你需要“或”在一起50个谓词的答案,需要49个,所以额外的费用是49 * [OR的成本] [节点数]。如果搜索-50,则额外成本为49 [访问树节点的成本] * [节点数]。因此,问题是“或”的成本是否低于“访问树节点”的成本。 “或”在大多数机器上都非常快,因为它只使用缓存中已有的寄存器和值。访问树节点可能非常快,但可能有几个指令;更糟糕的是,它触及记忆。如果你的树大到不适合缓存,那么如果谓词很便宜,你的搜索成本可能会受到内存访问时间的影响。
现在,我们可以用一些有趣的方式“欺骗”。首先,它可能是谓词有一些关系;如果谓词A暗示谓词B,我可以先检查B,如果是假,我不需要测试A.这可以减少“或”的数量,但对树访问没有帮助。其次,可能是谓词共享子测试,例如,谓词A实际上是“a1和a2”,而B实际上是“a1和a2”;在这种情况下,您可以对谓词进行因子分析并评估子谓词的次数较少;你只需要为每个节点评估一次“a1”。使用扫描多重技术并不容易。可能是某些谓词失败意味着不需要搜索子树;这里50个搜索可能会变得更快,因为每个搜索只会检查必要的子树,其中搜索一次将非常需要搜索到所有谓词同意的节点是一个停止点。
但是,对于每个谓词,您的程序可能会有不同的反应。所以你的程序结构实际上是一组“if p1(node)then a1(node)”。如果谓词便宜并且触发频率相对较高,那么这些操作可能是一个主导成本(比导航树节点更昂贵),然后这两种技术在性能方面都会很好。
最后,如果谓词和操作很复杂,您可能无法轻易猜出哪一个更便宜。很好,对两个搜索进行编码(不是 硬)并在实际数据上进行测量。