这里是二叉树的类型
type tree =
| Node of tree * int * tree
| Null;;
我要解决以下问题:
编写一个函数tree -> tree -> int
,该函数返回一个数字,该数字表示向下(从根开始)多少级别的树基本上是相同的(节点和相同形状的相同值)。这是我写的解决方案:
let rec identical l1 l2 =
match (l1, l2) with
| ([], []) -> true
| ((tree1, s1) :: t1, (tree2, s2) :: t2) ->
if s1 = s2 then
match (tree1, tree2) with
| (Null, Null) -> identical t1 t2
| (_, Null) -> false
| (Null, _) -> false
| (Node (l1, x1, r1), Node (l2, x2, r2)) ->
if x1 = x2 then identical t1 t2
else false
else false;;
let unfold l =
let l = List.filter (fun (a, b) ->
if a = Null then false else true) l in
if List.length l = 0 then raise Nulls else
List.fold_left (fun acc (a, b) ->
match a with
| Node (l, x, r) ->
(l, "l") :: (r, "r") :: acc) [] l;;
let compare t1 t2 =
let rec aux l1 l2 result =
if (List.length l1 <> List.length l2)
then result
else
if (identical l1 l2) then
try
aux (unfold l1) (unfold l2) (result + 1)
with
| Nulls -> result
else
result
in aux [(t1, "r")] [(t2, "r")] 0;;
问题是我对这段代码非常不满意 - 即使对我来说也很难理解。我正在做的事情主要是在树的每个层面上我创建一个左右树的列表,其中包含相应级别上的所有子树(以及子树是用于确定形状的左子或右子)然后在每个级别上比较此列表。如果它们是相同的,我会增加结果,如果不是 - 我返回结果。
但是当我使用这个&#34;算法&#34;我最终得到了这个复杂的代码。那么它可以做得更简单吗?
答案 0 :(得分:2)
更好的算法就是进行标准深度优先搜索。当你或者a)找到差异,或者b)达到你在前一个分支中已经找到差异的深度时停止并备份。
答案 1 :(得分:2)
我想提出以下代码:
let rec compare_tree t1 t2 =
match (t1, t2) with
| (Null, Null) | (Null, _ ) | ( _ , Null ) -> 0
| (Node (t1_l, x, t1_r), Node (t2_l, y, t2_r)) ->
if x=y then
1 + min
(compare_tree t1_l t2_l)
(compare_tree t1_r t2_r)
else 0;;
两种测试模式:
let t1 = Node (Node (Null,1,Null),1,Node (Null, 2, Null));;
let t2 = Node (Node (Null,1,Null),1,Node (Null, 3, Null));;
let c = compare_tree t1 t2 in
Printf.printf "compare = %d\n" c
;;
let t1 = Node (Node (Null,1,Null),1,Node (Null, 2, Null));;
let t2 = Node (Node (Null,1,Null),1,Node (Node (Null,1,Null), 2, Null));;
let c = compare_tree t1 t2 in
Printf.printf "compare = %d\n" c
;;
第一个测试返回1:只有级别1(int 1)在两个树中都相同,但是在级别2上,权限上的子树不同(2对3)。 第二个测试返回2,因为头是相同的,并且2个子树具有相同的值,接下来的是附加子树。 这是正确的预期行为吗?