我必须创建一个用于存储单词的类型树,就像树的每个节点都会有一个字母和下一个字符的列表(所以具有相同根的单词将共享相同的“部分/分支”树的基本上是一个n-ary,用作词典。 全部使用Caml语言
答案 0 :(得分:2)
好吧,我不知道它是否是家庭作业,但我还是会回答:
首先,我们需要为字母定义签名类型。
module type LS = sig
type t
val compare : t -> t -> int
end
然后,我们需要定义我们的结构:
module Make (L : LS) = struct
module M = Map.Make(L)
type elt = L.t list
type t = { word : bool; branches : t M.t }
let empty = { word = false; branches = M.empty }
let is_empty t = not t.word && M.is_empty t.branches
let rec mem x t =
match x with
| [] -> t.word
| c :: cl -> try mem cl (M.find c t.branches)
with Not_found -> false
let rec add x t =
match x with
| [] -> if t.word then t else { t with word = true }
| c :: cl ->
let b = try M.find c t.branches with Not_found -> empty in
{ t with branches = M.add c (add cl b) t.branches }
end
现在,一步一步:
module Make (L : LS) = struct
是一个仿函数,如果我们给它一个LS
类型的模块作为参数,它将返回一个新模块module M = Map.Make(L)
type elt = L.t list
type t = { word : bool; branches : t M.t }
这是复杂的一点,一旦你拥有它,一切都开始清晰。我们需要表示一个节点(正如您在Wikipedia page of tries中看到的那样)。我的代表是:节点是
Map
仿函数。因此,我的字段branches
是与某些字母trie
相关联的字段(这就是我写branches : t M.t
的原因)。然后,一个元素是一个字母列表,您将找出我选择此类型而不是string
的原因。let empty = { word = false; branches = M.empty }
空的trie是没有分支的记录(因此,只是根),而且这个根不是一个单词(所以word = false
)(同一个is_empty
的想法) let rec mem x t =
match x with
| [] -> t.word
| c :: cl -> try mem cl (M.find c t.branches)
with Not_found -> false
这里变得有趣。我的单词是一个字母列表,如果我想知道一个单词是否在我的trie中,我需要通过这个列表进行递归函数。
word
是true
还是false
。 cl
) let rec add x t =
match x with
| [] -> if t.word then t else { t with word = true }
| c :: cl ->
let b = try M.find c t.branches with Not_found -> empty in
{ t with branches = M.add c (add cl b) t.branches }
同样的想法。如果我想添加一个词:
word
已经true
,则表示此词已添加,我不做任何事情。如果word
为false
,我只返回相同的分支(trie),但word
等于true
。c
,我会在当前节点中找到与其对应的分支(try M.find c t.branches with Not_found -> empty
)并且我没有这样的分支,我只返回一个空的,然后我递归地将其余的字母添加到此分支,并将此新分支添加到与字母c
关联的当前节点的分支(如果此分支已存在,则将在我使用时替换它字典)在这里,我们从空的trie开始,我们将添加到, top 和 tea 。
如果我们不想使用仿函数,我们可以这样做:
type elt = char list
type t = { word : bool; branches : (char * t) list }
let empty = { word = false; branches = [] }
let is_empty t = not t.word && t.branches = []
let find c l =
let rec aux = function
| [] -> raise Not_found
| (c', t) :: tl when c' = c -> t
| _ :: tl -> aux tl
in aux l
let rec mem x t =
match x with
| [] -> t.word
| c :: cl -> try mem cl (find c t.branches)
with Not_found -> false
let rec add x t =
match x with
| [] -> if t.word then t else { t with word = true }
| c :: cl ->
let b = try find c t.branches with Not_found -> empty in
{ t with branches = (c, (add cl b)) :: t.branches }