在Ocaml中插入trie的实现

时间:2017-03-18 08:21:24

标签: ocaml trie

我对如何更改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, []))])

1 个答案:

答案 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是旧结构被记住的地方。它在添加新字符之前从列表的部分重建旧结构。