相互递归数据类型
Mutually recursive datatypes
我正在尝试创建一对相互递归的数据类型来表示 OCaml 中的 red-black 树以用于家庭作业。但是,我对 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
您不能从子类型引用类型的子值吗?不寻找问题的实际答案只是语法澄清。
更新
我在最初尝试后得到了这个,但教授说它不是对相互递归的数据类型:
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
red-black 树是一种有时用于组织数值数据的树。它有两种类型的节点,黑色节点和红色节点。红色节点总是有一个数据和两个children,每个都是一个黑色节点。黑色节点可能有:1)一条数据和两个children是红色节点; 2)一条数据和两个children是黑节点;或 3) 无数据且无 children(即叶节点)。 (这不是 red-black 树的精确描述,但对本练习来说是成功的。)
编写一对相互递归的 OCaml 数据类型,表示 red-black 树中的红色节点和黑色节点。数据应该可以有任何类型,也就是你的类型在树中存储的数据类型应该是多态的。
这是一个错误:
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
^^^^^^^ ^^^^^^^
这里RedNode
应该是type构造函数,不是值构造函数。我怀疑您要再添加一种类型 'a red_node
并按如下方式定义 TwoRedNodes
分支:
| TwoRedNodes of 'a * ( 'a red_node * 'a red_node)
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 中的类型名称必须始终以小写字母开头(例如 list
、array
、ref
),但类型构造函数必须以大写字母开头(例如 Some
)。该类型是包含其所有构造函数的伞。
P.S.: 我认为你甚至不需要相互递归的数据类型来解决这个问题。以下应该有效:
type 'a node =
Red of 'a * ('a node * 'a node)
| Black of 'a option * ('a node option * 'a node option)
最终,红黑树的一对相互递归数据类型的实现是:
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;;
我正在尝试创建一对相互递归的数据类型来表示 OCaml 中的 red-black 树以用于家庭作业。但是,我对 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
您不能从子类型引用类型的子值吗?不寻找问题的实际答案只是语法澄清。
更新
我在最初尝试后得到了这个,但教授说它不是对相互递归的数据类型:
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 red-black 树是一种有时用于组织数值数据的树。它有两种类型的节点,黑色节点和红色节点。红色节点总是有一个数据和两个children,每个都是一个黑色节点。黑色节点可能有:1)一条数据和两个children是红色节点; 2)一条数据和两个children是黑节点;或 3) 无数据且无 children(即叶节点)。 (这不是 red-black 树的精确描述,但对本练习来说是成功的。)
编写一对相互递归的 OCaml 数据类型,表示 red-black 树中的红色节点和黑色节点。数据应该可以有任何类型,也就是你的类型在树中存储的数据类型应该是多态的。
这是一个错误:
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
^^^^^^^ ^^^^^^^
这里RedNode
应该是type构造函数,不是值构造函数。我怀疑您要再添加一种类型 'a red_node
并按如下方式定义 TwoRedNodes
分支:
| TwoRedNodes of 'a * ( 'a red_node * 'a red_node)
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 中的类型名称必须始终以小写字母开头(例如 list
、array
、ref
),但类型构造函数必须以大写字母开头(例如 Some
)。该类型是包含其所有构造函数的伞。
P.S.: 我认为你甚至不需要相互递归的数据类型来解决这个问题。以下应该有效:
type 'a node =
Red of 'a * ('a node * 'a node)
| Black of 'a option * ('a node option * 'a node option)
最终,红黑树的一对相互递归数据类型的实现是:
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;;