寻找更好的比较二叉树的解决方案

时间:2014-11-18 17:36:18

标签: algorithm tree ocaml

这里是二叉树的类型

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;我最终得到了这个复杂的代码。那么它可以做得更简单吗?

2 个答案:

答案 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个子树具有相同的值,接下来的是附加子树。 这是正确的预期行为吗?