我试图获得一个函数(作为参数给出一个集合)来返回一个集合,其元素是从主集合形成的所有子集.例如:{1; 2; 3} - > {{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}}
但是我并不完全知道如何创建一个允许我使用一组集合的模块.我应该将它定义为什么类型?
一组所有子集称为幂集.要实现算法,您实际上并不需要特殊的数据结构,因为您可以使用列表来表示集合.相应地,一组集合将是列表的列表.例如,
let rec superset = function | [] -> [[]] | x :: xs -> let ps = superset xs in ps @ List.map (fun ss -> x :: ss) ps
这是一个用法示例:
superset [1;2;3];;
- : int list list = [[]; [1]; [2]; [2; 1]; [3]; [3; 1]; [3; 2]; [3; 2; 1]
Run Code Online (Sandbox Code Playgroud)
如果你想使用真实的套装,就像杰弗里建议的那样.然后我们需要稍微调整算法,因为Set模块提供了一点点不同的接口.
module S = Set.Make(String)
module SS = Set.Make(S) let superset xs = S.fold (fun x ps -> SS.fold (fun ss -> SS.add (S.add x ss)) ps ps) xs (SS.singleton S.empty)
要运行算法并打印结果,我们需要将其转换回列表,因为OCaml toplevel不知道如何打印集合:
# superset (S.of_list ["1"; "2"; "3"]) |> SS.elements |> List.map S.elements;;
- : S.elt list list =
[[]; ["1"]; ["1"; "2"]; ["1"; "2"; "3"]; ["1"; "3"]; ["2"]; ["2"; "3"];
["3"]]
Run Code Online (Sandbox Code Playgroud)
现在,我们可以推广算法,以便它可以在任何有序类型上工作.
module Superset(T : Set.OrderedType) = struct module S = Set.Make(T)
module SS = Set.Make(S) let of_set xs = S.fold (fun x ps -> SS.fold (fun ss -> SS.add (S.add x ss)) ps ps) xs (SS.singleton S.empty) end
现在我们可以运行它:
# module Superset_of_strings = Superset(String);;
# open Superset_of_string;;
# of_set (S.of_list ["1"; "2"; "3"]) |> SS.elements |> List.map S.elements;;
- : S.elt list list =
[[]; ["1"]; ["1"; "2"]; ["1"; "2"; "3"]; ["1"; "3"]; ["2"]; ["2"; "3"];
["3"]]
Run Code Online (Sandbox Code Playgroud)