簡體   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