我有以下树:
2
/ \
3 5
/ / \
6 4 1
以下列方式表示,顺序:
id parent
------------
2 null
3 2
6 3
5 2
4 5
1 5
将此扁平树存储在递归结构中 O(n)(O(n * log(n))是可以接受的,但不是很好)(我知道如何在< strong> O(n ^ 2),但我以DFS顺序存储数据,以便能够以更有效的方式“解析”它。 E.g:
class R {
int id;
List<R> children;
}
以JSON格式显示:
{
id: 2,
children: [
{
id: 3,
children: { ... }
},
{
id: 5,
children: { ... }
}
]
}
如何我可以这样做吗?编程语言并不重要,因为我可以用Java翻译它。
R r = new R();
Map<Long, Line> map = createMap2();
List<Line> vals = new ArrayList<Line>(map.values());
r.id = vals.get(0).id;
vals.remove(0);
r.children = createResource(vals, r.id);
...
private static List<R> createResource(List<Line> l, Long pid) {
List<R> lr = new ArrayList<R>();
if ( l.size() > 0 ) {
Long id = l.get(0).id;
Long p = l.get(0).pid;
l.remove(0);
if ( pid.equals(p) ) {
R r = new R();
r.id = id;
r.children = createResource(l, id);
lr.add(r);
}
else {
return createResource(l, pid); // of course, this is not ok
}
}
return lr;
}
上面代码中的问题是只有2
,3
和6
存储在递归结构(类R)中。我想在递归结构(R对象)中存储整个展平树结构(许多Line对象),而不仅仅是一些节点。
P.S。:问题得到了简化。我对特定解决方案不感兴趣,因为涉及许多领域和数千个条目。我也对在最坏情况下(不同种类的树)工作正常的解决方案感兴趣,因为这是用户的保证。
答案 0 :(得分:1)
这样的事情怎么样?在第一遍中,将父项哈希为子项的数组并标识根;在第二个中,从根开始,对于每个子节点,插入一个具有自己子节点的新对象,等等:
举个例子,第一遍将生成
parent_hash = {2:[3,5], 3:[6], 5:[4,1]}
root = 2
第二遍将会是:
object 2 -> object 3 -> object 6
-> object 5 -> object 4
-> object 1
done
答案 1 :(得分:0)
您的代码存在的问题是,一旦条目不满足p == pid
条件,它就会永远丢失。您应该打破循环并立即返回,而不是丢失条目。违规条目也应由R
上游的适当实例返回和处理。
答案 2 :(得分:0)
您可以轻松地在数组中表示整个树,因为树的每个节点都可以由数组中的索引表示。对于二叉树,索引 i 的子节点将在索引2 * i + 1和索引2 * i + 2处。然后将数组转换为任何其他表示将很简单。阵列本身对于平衡树来说是一个节省空间的表示,但是会为非常不平衡的树浪费大量空间。 (除非您处理大量数据,否则这无关紧要。)
如果对于大型不平衡树需要一种节省内存的方法,那么使用树的标准节点表示是有意义的。要从列表转换,您可以使用HashMap作为建议的גלעדברקן。但是,如果节点的id大部分是连续的(例如它们从1到6的示例),您也可以使用一个数组,其中数组的每个索引 i 用于存储ID为 i 的节点。这将使您可以轻松找到父节点,并在创建子节点时为其分配。
(参见my Trees tutorial将树存储为数组。)
答案 3 :(得分:0)
我找到了一个基于“DFS”顺序的简单解决方案。
即使我使用“线”对象或地图列表,这种方法仍然有效。
private static List<R> createResource(List<Line> l, Long pid) {
List<R> lr = new ArrayList<R>();
for ( Line line : l ) {
if ( line is a children ) {
R r = new R();
r.id = id;
l.remove(0);
r.children = createResource(l, line.id);
lr.add(r);
}
}
return lr;
}
它似乎在O(n ^ 2)中,因为所有元素都有for
循环+递归,但它在 O(n)中。由于DFS订单,调用createResource
的下一个元素位于第一个位置(0 - > O(1))。因为递归需要每个元素=&gt;复杂性是 O(n)。
但是如果订单不是DFS订单(可能涉及Map
不是LinkedHashMap
),我推荐包含父类数组的解决方案。 (根据גלעדברקן)