我对如何更改add
功能的代码一无所知。
type trie = Node of bool * (char * trie) list
let explode word =
let rec explode' i acc =
if i < 0 then acc else explode' (i-1) (word.[i] :: acc)
in explode' (String.length word - 1) []
let rec exists w tr = match w, tr with
| [], Node (b, _) -> b
| h::t, Node (_, l) -> try exists t (List.assoc h l) with Not_found -> false
let rec add w tr = match w, tr with
| [], Node (_, l) -> Node (true, l)
| h :: t, Node (b, l) -> try add t (List.assoc h l)
with Not_found -> Node (false, (h, add t tr) :: l)
问题是当List.assoc h l
发现某些内容时,我没有跟踪我的结构,在递归调用期间没有构建Node
所以我丢失了数据。
示例:
# let empty = Node(true, []);;
- : trie = Node (true, [])
# let w = explode "hi";;
val w : char list = ['h'; 'i']
# let ww = explode "hit";;
val ww : char list = ['h'; 'i'; 't']
# let tr = add w x;;
val tr : trie = Node (false, [('h', Node (false, [('i', Node (true, []))]))])
# add ww tr;;
- : trie = Node (false, [('t', Node (true, []))])
答案 0 :(得分:1)
您的基本计划似乎是使用List.assoc
来处理数据结构,然后在找到正确的位置时添加新节点。如果您可以修改结构,这是有道理的。但是,您的数据结构是不可变的。对于不可变数据,您的基本计划必须是构建 new 数据结构,而不是修改旧数据结构。所以你必须想象自己找到合适的位置,同时保持旧结构的沿途,然后从现场开始建立一个新的结构。
这是一些代码,它保存一个关联列表,计算到目前为止看到的字符实例数。请注意,它返回一个新的关联列表,而不是修改旧的关联列表(这是不可能的):
let rec add_char_count list char =
match list with
| [] -> [(char, 1)]
| (hchar, hcount) :: t ->
if hchar = char then (hchar, hcount + 1) :: t
else (hchar, hcount) :: add_char_count t char
递归调用(hchar, hcount) :: add_char_count t char
是旧结构被记住的地方。它在添加新字符之前从列表的部分重建旧结构。