繁体   English   中英

OCaml函数与数据类型树

[英]OCaml function with data type tree

我们给出一个包含两种元素的树。 它由以下数据结构定义。

type ( 'a , 'b ) tree =
   Empty
   | Vertexa of 'a * ( 'a , 'b ) tree list
   | Vertexb of 'b * ( 'a , 'b ) tree list

编写一个函数split:('a,'b)tree - >'list *'b list,它将'a'类型的所有元素保存到第一个列表,将所有类型'b'的元素保存在第二个列表中。

我有一个想法,递归地做这个,但我有点坚持这个。 即使它根本不起作用,我也会附上我的尝试:/

let rec one drevo_list=
    match drevo_list with
   | [Empty]->Empty 
   | Empty::tl -> one tl
   | Vertexa(a,b)::tl -> Vertexa(a,b@tl) 
   | Vertexb(a,b)::tl -> Vertexb(a,b@tl) 

此功能将列表转换为树。 我需要它用于递归,因为Vertexa或Vertexb中的第二个参数是一个列表。 这工作但但递归部分没有。

let rec split drevo=
   match drevo with
   | Empty -> [],[]
   | Vertexa(a,b)-> split (one b)
   | Vertexb(a,b)-> split (one b)

这部分不起作用,我不知道如何完成它。 有没有人知道如何完成这个?

您不需要drevo_list函数来解决此问题。 它实际上会引导你走错方向。

您需要使用List.map将拆分应用于树列表。 您将获得('a list * 'b list) list类型的值。 现在你需要一个帮助函数concat_pairs ,它将这个值展平为一对类型'a list * 'b list (参见标准concat函数)。 要实现此功能,您可以使用List.fold_left 其余的都是微不足道的。

注意,当然这是一个贪心的解决方案。 完成后,您可能会尝试找到更好的解决方案,更高效,尾递归。

这个函数至少有两个部分难以编写:

  1. 返回一对列表的函数需要在每个递归步骤中打包和解包其返回值,例如辅助函数,匹配语句或let绑定。 一种方法是编写一个函数,将一个元素插入一对内的列表中:

     let insertA a (xs, ys) = (a::xs, ys) let insertB b (xs, ys) = (xs, b::ys) 
  2. 对树类型和嵌入列表类型递归的函数需要两个递归模式的组合。 这可以使用一组相互递归的函数或使用列表的高阶组合器来解决。 以下是使用前一策略的解决方案概述:

     let rec split s = match s with | Empty -> ([], []) | Vertexa (a, ts) -> (* if we had just one t: insertA a (split t) *) | Vertexb (a, ts) -> (* if we had just one t: insertB b (split t) *) 

    因此,您需要一个函数splitMany : ('a, 'b) tree list -> ('a list, 'b list) ,可以为每个单独的树回调split

     and rec splitMany ts = match ts with | [] -> ([], []) | (t:ts') -> (* merge (split t) with (splitMany ts') *) 

    对于高阶函数方法,可以通过让函数将自身传递给一组高阶函数来避免显式的相互递归,从而不会在高阶函数的实现中纠缠它:

     let rec split s = match s with | Empty -> [],[] | Vertexa (a, ts) -> insertA (concat_pairs (map split ts)) | Vertexb (a, ts) -> insertB (concat_pairs (map split ts)) 

    其中concat_pairs是ivg的发明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM