【发布时间】:2020-03-19 17:22:47
【问题描述】:
我有一个树类型:
type tree = Vertex of int * tree list;;
我的递归相等定义是,如果两棵树的整数相等且所有子树都相等,则两棵树相等。
如何构建函数
topo: tree -> tree list
创建深度优先搜索顺序的所有树的列表,每棵树出现一次且仅出现一次(根据相等定义)?我想以一种计算有效的方式来做到这一点。也许使用惰性或哈希图?
这是我的尝试,长度太大时代码会爆炸:
type tree = Vertex of int * (tree list)
let rec base = function
| 0 -> Vertex (0, [])
| i -> Vertex (i, [base (i - 1)])
let rec range = function
| 0 -> [0]
| i -> i :: range (i - 1)
let agg i = Vertex (-1, List.map base (range i))
let rec equals (a: tree) (b: tree) : bool =
let rec deep_match a_dep b_dep = match a_dep, b_dep with
| [], [] -> true
| [], _
| _, [] -> false
| x::xs, y::ys -> equals x y && deep_match xs ys
in
let Vertex (ai, al) = a in
let Vertex (bi, bl) = b in
ai = bi && deep_match al bl
let rec in_list (a: tree) (l: tree list) : bool = match l with
| [] -> false
| hd::tl -> equals a hd || in_list a tl
let rec topological (pool: tree list) (t: tree) : tree list =
if in_list t pool then pool else
t::match t with
| Vertex(_, []) -> pool
| Vertex(_, deps) -> List.fold_left topological pool deps
let big_agg = agg 100_000
let topo_ordered = topological [] big_agg;;
Printf.printf "len %i\n" (List.length topo_ordered)
【问题讨论】:
-
你自己尝试过什么,你在哪里卡住了? Stack Overflow 不是一个代码编写服务,而是一个获得特定编程问题帮助的地方。请参阅 How to Ask 以及 help center 中的主题内容。
-
我尝试研究如何懒惰地执行此操作,并使用哈希映射执行此操作,但我被卡住了。在 C 语言中这似乎是一个简单的问题:返回指针并记住最递归的树生成器。然后用使用指针的字典折叠。我看不到如何在 OCaml 中做类似的事情
-
所以假设我的 DAG 有 n 个“基”节点和一个“父节点”。假设从底数 n 到底数 n - 1 有一条边,一直到底数 0 没有边。然后假设从父节点到每个基节点都有一条边。即使这个图只有 n + 1 个顶点和 2n - 1 条边,路径的数量随着 n ^ 2 的增长而增长。当我尝试使用直接相等运算符编写这个函数时,程序完成所花费的时间会爆炸,而你不能用 n=100000 来评估它。
-
我已经添加了我的尝试!
-
我要问的问题与并行性无关。问题是在编写代码时爬取树所花费的时间远远超过线性时间。目标是找到一种在 OCaml 中编写代码的方法,使得它只需要线性时间。
标签: functional-programming ocaml