我正在尝试将图形结构映射到我在下面显示的结构中。
以下是我需要映射的图表类型的示例
其中箭头始终具有从左到右的方向。
这是我要找的结果。
目标是生成这样的XML:
<root>
<seq>
<mod1/>
<flow>
<seq>
<mod4/>
<mod7/>
</seq>
<seq>
<flow>
<seq>
<flow>
<mod4/>
<mod3/>
</flow>
<mod6/>
</seq>
<seq>
<flow>
<mod4/>
<mod3/>
<mod2/>
</flow>
<mod5/>
</seq>
</flow>
<mod8/>
</seq>
</flow>
</seq>
</root>
我可以使用任何算法吗?
我认为它不相关,但我正在解析JSON以使用JAVA 7编写XML。 框是Web服务,箭头表示输入和输出参数,因此,例如,模块1在模块1,2,3和4完成后调用,其输出是其输入。
答案 0 :(得分:5)
您在上面显示的图表有周期,因此它永远不能表示为树。通常,树被定义为没有循环的连通图。因此,只有一种方法可以将常规图转换为树 - 删除周期并在需要时连接它。
编辑:根据您的编辑,图表是定向的,因此您将拥有一个DAG,它不再是一棵树,而是有几个有趣的属性。
答案 1 :(得分:3)
(不是答案,但出于虚假的原因,我建议的编辑遭到拒绝。)
正式问题重述,基于此问题的评论和另一个
输入是有限集X上的partial order≤ X ,由具有顶点X的非循环有向图指定。输出为series-parallel partial order≤ Y 在有限集Y上,由一元素偏序的序列和并行组合指定,并且映射f:Y→X,明确指定,这样,对于每个最大链x 1 &lt; X ...&lt; X x n (= transitive reduction中的源 - 汇路径输入图),恰好存在一个最大链y 1 &lt; Y ...&lt; Y y n with对于所有j∈{1,...,n},f(y j )= x j 。我们想要| Y |尽可能小。
答案 2 :(得分:2)
如果路径是定向的,那么将存在通过复制叶节点以对应于多个路径而形成的等效树结构。如果结构没有有向路径,那么我认为在一般情况下没有相应的树结构。
修改强>
根据新信息,这是一个有向图,等效树结构是:
1
2
5
8
3
5
8
6
8
4
6
8
7
并且导出它的算法是图的中缀遍历,当没有传出路径时停止在每个肢体上。
答案 3 :(得分:1)
问题仍然有点不清楚,但我感觉你需要执行图表的图表序列化或拓扑排序。这只能应用于DAG,因为循环的存在可以被解释为依赖循环。
答案 4 :(得分:0)
您展示的图片表明该方法应该从最后向后工作。首先查找没有子节点的节点 - 在本例中为8和7.形成树的“双主干”。然后你找到8和7的所有父母。也寻找没有父母的模块 - 在这种情况下1.称之为祖先。这是“终点”。最后,对于每组公共节点,我们声明一个“族”。具有共同子节点的节点是系列节点 - 即使同一节点可以属于多个族。只有一个父节点的节点是该父节点的一部分。
对于8,你会找到5和6.家庭A.
对于7,你会发现4.家庭B. 7只有一个父母,所以我们称4个家庭为B。
称这些为“第2代”。
对于第二代,寻找父母。
家庭A: 5 - &gt; 2,3,4。家庭C. 6 - &gt; 3,4。家庭D
B家庭: 4 - &gt; 1 - 大家庭到达祖先。此路径现已完成。我们可以捕获一条路径为1-4-7-end(所有“B族”)
现在寻找第3代的父母:
of 5(C家庭):
2 - &gt; 1
3 - &gt; 1
4 - &gt; 1
同一家庭的同一家庭成员是“亲密的兄弟姐妹”并在上方和下方获得<flow>
。
of 6(D家庭): 3 - &gt; 1 4 - &gt; 1 另一个亲密的家庭
由于这些家庭最终都指向了祖先,我们还需要另外一个。
因此,我们拥有所描述的每个过程的完整祖先。现在我们使用上面的“家庭”转换为您的流程图。
Your desired XML - annotated with the families. You can see how this works
<root>
<seq>
<mod1/> // the ancestor
<flow>
<seq> // family B - straight through.
<mod4/>
<mod7/>
</seq>
<seq>
<flow>
<seq>
<flow> // close family D
<mod4/>
<mod3/>
</flow>
<mod6/> // child of D
</seq>
<seq>
<flow> // close family C
<mod4/>
<mod3/>
<mod2/>
</flow>
<mod5/> // child of C
</seq>
</flow>
<mod8/>
</seq>
</flow>
</seq>
</root>
这有用吗,还是我完全不合适?
编辑:关于“中间关闭流程”的主题,有以下想法:如果一个家庭拥有与另一个家庭相同的(大)孩子,并且他们拥有相同的(大)父母,那么他们的流量可以在该水平上组合。要发现这一点,您需要为每个家庭保留一份“直接血统”列表,并且您需要针对每个家庭迭代搜索此列表,以找到共有(大)父母和普通(大)子女的情况。以一般方式解决这个问题需要花费比今晚更多的努力,因为你已经表明你已经接近解决方案了,我会把它留在这里......
答案 5 :(得分:0)
最后,我找到了一个完成这项工作的算法。这是适合所有试图帮助我的人:
首先,我在草图1中从DAG构建了一个倒置的生成树。所以我从模块7和8开始,向后构建树以及复制模块。
之后,我创建名为FLOW和SEQUENCE的虚拟节点,并在树中引入它们,以便每个MODULE节点都是SEQUENCE节点的子节点。生成分支是SEQUENCE节点,它们是FLOW节点的子节点。我认为这个步骤足够直观,但重要的是要理解我们需要虚拟节点,这样我们就可以关闭FLOW节点,这些节点是从一个节点分裂到多个节点的。
之后我首先回顾树深度,对于每个模块(我们称之为驱动程序),我将它的孩子与司机兄弟姐妹的孩子进行比较。如果它们不匹配,我会继续与驾驶员的兄弟姐妹的孙子一起下来,这样,从驾驶员的兄弟姐妹中出来的所有分支必须通过与驾驶员相同的节点。从图形上看,这意味着在某些时候,两个节点都需要完全相同的模块。
如果匹配,我会从重合的节点向下清理合并的分支,这意味着我将它们从父母身上切掉。从那里开始,它与驱动程序SEQUENCE节点一起进入一个新的SEQUENCE节点,进入同一个FLOW节点。
在遍历整棵树之后,只要合并完成,我们就会再次遍历树,这次是一段更大的关系。这意味着我们不是比较驾驶员的孩子,而是比较驾驶员的好孩子。
最后一步显然是要再次恢复树。
由于这些虚拟节点的编程意味着错综复杂,我遗留了一些概念。主要是由于一旦引入了虚拟节点,所有父子关系都会丢失。但我希望大家的想法得到了解。