在ocaml中创建一个完美平衡的二叉树

时间:2017-03-20 18:46:51

标签: ocaml

我一直在编写一些代码来尝试从数组中创建一个完美平衡的树,但是当我遇到问题并且使列表大于3个元素时我得到错误"在评估期间堆栈溢出(循环递归) ?)&#34 ;.我是因为这是因为我的执行效率很低或者我犯了其他一些错误?感谢您的帮助,我们将非常感谢,代码如下。

ps - 我也意识到我应该使用fold_left作为辅助函数,但是直到这样做之后我才明白它

 type 'a binary_tree =
      | Empty
      | Node of 'a * 'a binary_tree * 'a binary_tree;;


 let length lst = 
     let rec aux acc = function
          | [] -> acc
          | x::xs -> aux (acc+1) xs
     in
     aux 0 lst;;

 let mid lst = 
     let rec aux count = function
         | [] -> None
         | x::xs -> if (count=0) then Some x else aux (count-1) xs
     in
     aux ((length lst)/2) lst;;

  let left lst = 
      let rec aux count acc = function
           | [] -> []
           | x::xs -> if (count=0) then acc else aux (count-1) (acc@[x]) xs
       in
       aux ((length lst)/2) [] lst;;


  let right lst = 
      let rec aux count = function
          | [] -> []
          | x::y::xs -> if (count=0) then xs else aux (count-1) (y::xs)
      in
      aux (((length lst)/2)-1) lst;;

  let rec createTree lst = match lst with
      | [x] -> Node((Some x),Empty,Empty)
      | xs -> Node((mid xs), (createTree(left xs)), (createTree(right xs)));;

2 个答案:

答案 0 :(得分:3)

尽管实现效率很高,但递归循环仍然存在 从缺少的空案例[]开始:从left [] = []right [] = []开始,createTree []被扩展为Node(mid [], createTree [], createTree []),这会导致堆栈溢出。

在效率方面,请注意,由于为每个元素计算的列表连接left,您的较差函数为acc @ [x],其输入大小为二次而非线性。对于这种情况,通过在left末尾反转列表,性能会更好。

另一方面,在left函数中将midrightpartition组合在一起以避免重复可能是有意义的。

答案 1 :(得分:1)

您可以直接使用List.length而不是自己定义;)

此外,如果您不特别需要保留元素的顺序,则可以通过获取列表的第一个元素来计算midleftright值,并且如下所示拆分其余部分:

let split l = 
  let rec loop left right flag rest =
    match rest with
    | [] -> left,right
    | h::t -> 
       if flag then loop (h::left) right (not flag) t
       else loop left (h::right) (not flag) t
  in loop [] [] true l

通过在每一步将flag切换为not flag,您可以将每两个元素中的一个元素发送到左侧列表中,将另一个元素发送到右侧列表中。 您的createTree功能因此变为:

let rec createTree lst = 
  match lst with
  | [] -> Empty
  | h::t -> 
    let left,right = split t in  
    Node(h, (createTree left), (createTree right))

希望它会有所帮助:)