在二郎双链接数据结构(Doubly linked data structures in erlang

2019-08-04 03:35发布

您好我想作一棵树,保持父母与子女之间的双向引用。 但是,这似乎是不可能才达到,因为当我创建第一个对象,我没有其他的一个,因此还不能对它的引用。 下面是一些示例代码。

-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)

-record(node,{prev,name,next}).

main()->
    A = #node{prev=nil,
          name="node-A",
          next=B}, % variable B is unbound
    B = #node{prev=A,
          name="node-B",
          next=nil},
    LinkedList = A.

是否有实现这种结构的一种方式。

Answer 1:

当你有“链接”(如指针)可以使双向链表。 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"]



Answer 2:

您可以检查这在FERD的如何实现的拉链库



Answer 3:

不,是实现双向链表中的二郎神,因为所有的数据是不可变的没有直接的方法。 而且即使你可以设置它(你不能),你无法为所有的数据不变的任何事情。 这里提出的其他解决方案告诉你避过此通过建立它们的行为在一个双向链表时装数据结构的方式。 但并非如此。



Answer 4:

如果你真的需要做这样的事情,你可以使用某种标识来参考您的节点。 例如

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}.


Answer 5:

你可以这样定义一个记录

-record(my_node,{leftchild,rightchild,父母,值}。

并存储你的树在ETS表,

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}}).

不过,可能是你应该多看一眼“二郎风格”的数据表示为您解决问题。 还有与我建议,如果有多个进程访问树解决问题,因为树的更新不是原子。 在这种情况下,你应该使用Mnesia的,数据的基础层之上ETS,将带给你的原子事务。



文章来源: Doubly linked data structures in erlang
标签: tree erlang