Java 在扩展树和压缩树之间快速转换

Java 在扩展树和压缩树之间快速转换,java,algorithm,optimization,tree,decision-tree,Java,Algorithm,Optimization,Tree,Decision Tree,我有两种树格式(扩展树和压缩树)。它们是一些决策树,一些尝试。每个节点可以有任意数量的子节点。叶节点还包含数据。扩展树本质上是扩展出来的逻辑,每个子树/节点中没有AND/OR。压缩的树基本上将扩展的节点收集在一起,这样人类可以更容易地编辑(减少重复) 我正在寻找一种在两棵树之间进行转换的有效方法,因为我当前的算法相当幼稚(它比O(n^2)稍好)。它开始崩溃,因为我在扩展的树中遇到了约200万个节点 是否有一个关键字,我可以搜索类似的问题?这有点像“反转”树(一棵树中节点中的数据成为另一棵树中的路

我有两种树格式(扩展树和压缩树)。它们是一些决策树,一些尝试。每个节点可以有任意数量的子节点。叶节点还包含数据。扩展树本质上是扩展出来的逻辑,每个子树/节点中没有AND/OR。压缩的树基本上将扩展的节点收集在一起,这样人类可以更容易地编辑(减少重复)

我正在寻找一种在两棵树之间进行转换的有效方法,因为我当前的算法相当幼稚(它比O(n^2)稍好)。它开始崩溃,因为我在扩展的树中遇到了约200万个节点

是否有一个关键字,我可以搜索类似的问题?这有点像“反转”树(一棵树中节点中的数据成为另一棵树中的路径),尽管“反转二叉树”意味着不同的操作(更像顺序的水平镜像)。决策树表转换似乎可能相关,但数据格式略有不同

限制条件:

  • 扩展的树格式确实不容易更改,但是如果通过更改压缩的树格式可以大幅提高速度,则可以修改压缩的树格式
  • 目前有200万个扩展节点,未来几年的上限为1000万个节点(实际可能约为500万个)
  • 理想情况下,将JVM总内存限制为6GB,这样就可以在客户端完成,但如果我们可以使用更多RAM使其速度提高几个数量级,则愿意将其移动到30GB的服务器机器上(尽管之后我们开始遇到网络传输延迟)
  • 在一个完美的世界中,转换将花费<30秒。现在我大约在3-4分钟
扩展和压缩树示例:

从展开->压缩时发生了什么:

  • 路径和数据基本反转(expandedTree数据->compactedTree路径和expandedTree路径->compactedTree数据) **扩展节点数据用于构建压缩树中的路径(在扩展节点中以parens表示) **扩展节点中的路径进入压缩节点数据中的键/值映射(根据需要组合重复项)
  • 扩展节点data2和data3压缩到压缩树中的单个节点中,因为它们的压缩路径相同(某些/Expanded/path),并且它们的键/值对可以一起进行OR运算(key1==Value1和(key2==value2或value4))
  • 无法压缩扩展节点data2和data4,因为它们的压缩路径不相等
  • 无法压缩扩展节点data1和data2+data3,因为它们的路径不兼容(data1对key3=value3有data2+data3没有的附加约束)
要提供有关格式的更多详细信息,请执行以下操作:

扩大:

  • 树下的路径是一系列键/值对。所以它基本上就像一个决策树或trie
  • 只有叶数据节点对压缩树很重要。中间路径节点可以很容易地重新生成,因为它们不包含任何数据
  • 每个数据节点都有一些必须记住的ID,因为这是主(持久)格式
  • 每个数据节点在其中存储一个压缩路径,以便在转换为压缩树时知道要去哪里。这会占用大量的空间(以及转换过程中的时间),因此用另一种方法进行转换将是理想的。我正在考虑一起删除用户定义的分组(从扩展节点中删除此字符串),而是在压缩树转换期间将树上的相等节点压缩,尽管不确定这样做会获得多少速度,并且用户定义的分组目前对用户有用
压实:

  • 树下的路径存储在展开树节点中,与给定节点在展开路径中的位置无关(在完全平衡的完整树中,最左边的叶和最右边的叶可能具有相同的压缩路径,因此最终位于相同的压缩节点中,即使它们位于不同的展开子树中)
  • ID在这里并不重要(事实上,如果没有人类可以处理的话,它将是理想的)。但是我们是否需要记住扩展树ID,以便以某种方式完美地重建扩展树。这是一个棘手的部分
  • 来自扩展树的路径在压缩节点的数据节点中的键/值映射中结束(参见示例)。这基本上将扩展节点与and和OR一起分组为单个压缩节点(因此压缩)。这似乎是压缩逻辑表达式时必须解决的常见问题
谢谢