Tree erlang中的双链接数据结构
嗨,我想做一棵树,保持父母和孩子之间的双向引用。但这似乎不可能实现,因为当我创建第一个对象时,我还没有另一个对象,因此无法引用它。下面是一些示例代码Tree erlang中的双链接数据结构,tree,erlang,Tree,Erlang,嗨,我想做一棵树,保持父母和孩子之间的双向引用。但这似乎不可能实现,因为当我创建第一个对象时,我还没有另一个对象,因此无法引用它。下面是一些示例代码 -record(node,{name,children,root}). main()-> A = #node{name="node-A", children=[B], %variable B is unbound root=nil}, B = #node{name="node-B",
-record(node,{name,children,root}).
main()->
A = #node{name="node-A",
children=[B], %variable B is unbound
root=nil},
B = #node{name="node-B",
children=[],
root=A},
Tree = A.
这个问题的另一个例子是实现双链接列表(http://en.wikipedia.org/wiki/Doubly_linked_list)
有没有一种方法可以实现这种结构。当你有“链接”(如指针)时,你可以创建双链接列表。在erlang中,您没有这样的链接,甚至没有真正的变量,您无法更改它们。以下是循环列表的一些示例,但应谨慎执行: 也许你可以告诉我们为什么需要双链接树?也许在erlang中有更好的解决方案 编辑:你可以使用。树可以表示为循环图,其中顶点从A到B和从B到A。具有根节点A和子节点B和C的树示例:
main()->
Tree = digraph:new([cyclic]),
A = digraph:add_vertex(Tree,"vertexA"),
B = digraph:add_vertex(Tree,"vertexB"),
C = digraph:add_vertex(Tree,"vertexC"),
digraph:add_edge(Tree, A, B),
digraph:add_edge(Tree, B, A),
digraph:add_edge(Tree, A, C),
digraph:add_edge(Tree, C, A),
digraph:get_path(Tree, B, C).
结果:[“vertexB”、“vertexA”、“vertexC”]
如果您确实需要这样做,您可以使用某种ID来引用节点。例如
A = #node{name="node-A",
children=["node-B"],
parent=nil},
B = #node{name="node-B",
children=[],
parent="node-A"},
NodeDict = dict:from_list([{A#node.name, A}, {B#node.name, B}]),
Tree = #tree{root=A#node.name, nodes=NodeDict}.
您可以检查如何在ferd的库中实现此功能 -记录(我的_节点,{leftchild,righchild,parent,value}) 并将您的树存储在ets表中
ets:new(my_tree,[named_table, ordered_set, public]),
...
然后您可以使用表键作为“指针”来管理链接
但也许你应该多看看“erlang风格”解决您的问题的数据表示法。如果有多个进程访问树,我建议的解决方案也有一个问题,因为树的更新不是原子的。在这种情况下,您应该使用mnesia,ets上的一个数据库层,它将为您带来原子事务。不,没有直接的方法来实现因为所有数据都是不可变的,所以在Erlang中使用ubly链接列表。即使您可以设置它(您不能)如果所有数据都是不可变的,你就不能做任何事情。这里介绍的其他解决方案通过构建以双链表方式运行的数据结构来解决这个问题。但是没有。为什么不在a中定义你的结构?定义子节点默认为未定义的位置。然后在创建节点B后,创建NodeA=B#node{children=A}…很抱歉,这不管用。希望我知道如何删除便笺为什么不先创建子项,然后为其分配父项?或者创建父项并为其指定默认子项,然后在子项准备好后更新父项?哦,这很好。很高兴我发现了这一点:)。是否有一种方法可以跟踪/保留对链接列表结尾的引用,以便在erlang中执行追加操作O(1)?否,您不能添加到列表结尾。但是你可以用我的例子来模拟。有向图使用ets,它具有O(1)插入成本。
ets:new(my_tree,[named_table, ordered_set, public]),
...
Root = {make_ref(),#my_node{value=somevalue}}
ets:insert(my_tree,Root),
A_child = {make_ref(),#my_node{value=othervalue}},
addchild(Root,A_child,left),
...
addchild(Parent={Pref,Pval},Child={Cref,Cval},left) ->
ets:insert(my_tree,{Pref,Pval#my_node{leftchild=Cref}}),
ets:insert(my_tree,{Cref,Cval#my_node{parent=Pref}});
addchild(Parent={Pref,Pval},Child={Cref,Cval},right) ->
ets:insert(my_tree,{Pref,Pval#my_node{rightchild=Cref}}),
ets:insert(my_tree,{Cref,Cval#my_node{parent=Pref}}).