2015-06-21 68 views
4

我正在尝试创建一对相互递归的数据类型来表示OCaml中用于作业分配的红黑树。但是,我对OCaml语言非常不熟悉,所以我有一些语法问题。相互递归数据类型

这里就是我来了这么远:

type 'a red_black_tree = 
| RedNode of 'a * ('a black_node * 'a black_node) 
| BlackNode of 'a black_node 
and 'a black_node = 
| TwoRedNodes of 'a * ('a RedNode * 'a RedNode) 
| TwoBlackNodes of 'a * ('a black_node * 'a black_node) 
| BlackLeaf;; 

当我输入到这一点的OCaml它给了我:

utop # type 'a red_black_tree = 
| RedNode of 'a * ('a black_node * 'a black_node) 
| BlackNode of 'a black_node 
and 'a black_node = 
| TwoRedNodes of 'a * ('a RedNode * 'a RedNode) 
| TwoBlackNodes of 'a * ('a black_node * 'a black_node) 
| BlackLeaf;; 
Error: Syntax error 

您不能引用类型的子值从一个子类?没有寻找问题的实际答案,只是语法澄清。

UPDATE

我有这个最初的尝试之后,但它是由教授说,这是不是一个对相互递归的数据类型的:

type 'a red_black_tree = 
| RedNode of 'a red_node 
| BlackNode of 'a black_node 
and 'a red_node = 
| RedTree of 'a * ('a black_node * 'a black_node) 
and 'a black_node = 
| TwoRedNodes of 'a * ('a red_node * 'a red_node) 
| TwoBlackNodes of 'a * ('a black_node * 'a black_node) 
| BlackLeaf;; 

更新2

问题3 红黑树是一种有时用来组织数值数据的树。它有两种类型的节点,黑节点和红节点。红色节点总是有一个数据和两个孩子,每个孩子都是一个黑色节点。黑色节点可能有:1)一块数据和两个子节点是红色节点; 2)一个数据和两个黑人节点的孩子;或3)没有数据和没有孩子(即叶节点)。 (这不是红黑树的精确描述,但是适用于此练习。)

编写一对相互递归的OCaml数据类型,它们表示红黑树中的红色节点和黑色节点。数据应该能够具有任何类型,也就是说,您的类型应该是存储在树中的数据类型中的多态。

回答

2

最终,一对相互递归的数据类型为红黑树的实施是:

type ’a black_node = Leaf 
| RNode of ’a * ’a red_node * ’a red_node 
| BNode of ’a * ’a black_node * ’a black_node 
and ’a red_node = RedNode of ’a * ’a black_node * ’a black_node;; 
2

这是一个错误:

| TwoRedNodes of 'a * ('a RedNode * 'a RedNode) 
          ^^^^^^^  ^^^^^^^ 

这里RedNode应该是型构造,而不是一个值构造。我怀疑,那你要增加一个类型'a red_node,并定义TwoRedNodes分支如下:

| TwoRedNodes of 'a * ('a red_node * 'a red_node) 
+0

我更新我的帖子有这样的一个例子。然而,当我提出来的教授,她说,这是不是一个对递归类型 – dmcqu314

+0

的例子也许她是挑剔的,它不是一对,但特里普尔? ;)你可以指出她的事实,'red_node'取决于'black_node','black_node'取决于'red_node'。它不是相互递归吗? – ivg

+0

有时教授可能会非常严格。我也会发布该问题的描述。最糟糕的情况下,我会交出我得到的,因为它只有5/200点的任务。 – dmcqu314

4
type 'a red_node = 'a * ('a black_node * 'a black_node) 
and 'a black_node = ('a * ('a node * 'a node)) option 
and 'a node = 
    Red of 'a red_node 
    | Black of 'a black_node 

的表达,会告诉你“N”的基础上,什么样的节点最后更新你的问题。

(* to determine if a black node is a type 1 black node *) 
match n with 
| Black n' -> 
    begin match n' with 
    | Some n'' -> 
     begin match n'' with 
     | _, (Red _, Red _) -> "type 1 black node" 
     | _, (Black _, Black _) -> "type 2 black node" 
     | _ -> raise (Failure "invalid node") 
     end 
    | None -> "leaf node" 
    end 
| Red _ -> "red node";; 

在类型OCaml中的语义:OCaml中A型名称必须以一个小写字母(例如listarrayref)开始,但类型构造必须用大写字母(例如Some)开始。这个类型是一个包含所有构造函数的伞。

P.S .:我不认为你甚至需要这个问题的相互递归数据类型。下面应该工作:

type 'a node = 
    Red of 'a * ('a node * 'a node) 
    | Black of 'a option * ('a node option * 'a node option) 
+0

我同意你的需要进行相互递归的数据类型,但很可惜什么教授说了算不幸... – dmcqu314

+1

的主要部分,我仍然不清楚的是:1)一个数据块和两个孩子是红色节点; 2)一个数据和两个黑色节点的孩子。 ('节点*'是一个节点)将如何限制这一对齐? – dmcqu314

+0

它的节点类型不受限制。使用这种类型时,您应该始终将其匹配为同类。 – user1030453