Data structures 左撇子堆两个版本创建实现

Data structures 左撇子堆两个版本创建实现,data-structures,functional-programming,ocaml,leftist-tree,Data Structures,Functional Programming,Ocaml,Leftist Tree,最近,我在读《纯函数数据结构》一书 当我谈到左撇子_树的“练习3.2直接定义插入而不是通过调用合并”时,我实现了我的版本插入 let rec insert x t = try match t with | E -> T (1, x, E, E) | T (_, y, left, right ) -> match (Elem.compare x y) with | n when n < 0 -> makeT x left (insert y right)

最近,我在读《纯函数数据结构》一书 当我谈到左撇子_树的“练习3.2直接定义插入而不是通过调用合并”时,我实现了我的版本插入

 let rec insert x t =
try
  match t with
| E -> T (1, x, E, E)
| T (_, y, left, right ) ->
  match (Elem.compare x y) with
  | n when n < 0 -> makeT x left (insert y right)
  | 0 -> raise Same_elem
  | _ -> makeT y left (insert x right)
with
     Same_elem -> t

16。2015年10月更新

通过更精确地观察这两个实现,很容易发现差异在于合并一个基本树
T(1,x,E,E)
或插入一个元素
x
,我使用的图形可以更清楚地表达

所以我发现我的插入版本总是使用更复杂的方法来完成他的工作,并且没有利用左撇子树的优点,或者它总是在更糟糕的情况下工作,即使这个树结构是“左撇子”

如果我改变一小部分,两个代码将得到相同的结果

let rec insert x t =
  try
  match t with
  | E -> T (1, x, E, E)
  | T (_, y, left, right ) ->
    match (Elem.compare x y) with
    | n when n < 0 -> makeT x E t
    | 0 -> raise Same_elem
    | _ -> makeT y left (insert x right)
with
  Same_elem -> t
让rec插入x t=
尝试
匹配
|E->T(1,x,E,E)
|T(u,y,左,右)->
将(元素x和y)与
|n当n<0->市场x E t
|0->提出相同的元素
|->市场y左(插入x右)
具有
相同的元素->t
所以对于我的第一个问题:我认为答案并不准确。它可以真正构造一棵左派树,但总是在恶劣的情况下工作

第二个问题有点毫无意义(我不确定)。但对于这种情况来说,这仍然很有趣。例如,尽管合并版本的工作效率更高,但对于从一个列表中构造一棵树,而不需要我提到的插入顺序([“a”;“b”;“d”;“g”;“z”;“e”;“c”],[“c”;“e”;“z”;“g”;“d”;“b”;“a”]),如果顺序不重要,我认为它们是同一组。)合并函数无法选择更好的解决方案。(我认为[“a”;“b”;“d”;“g”;“z”;“e”;“c”]的树结构比[“c”;“e”;“z”;“g”;“d”;“b”;“a”]的树结构好)

现在我的问题是:

  • 每个次右脊椎为空的树结构是否为良好结构
  • 如果是,我们是否可以始终以任何输入顺序构造它

  • 每个次右脊椎为空的树只是一个列表。因此,对于列表来说,简单列表是更好的结构。运行时属性将与列表相同,这意味着插入例如将花费
    O(n)
    时间,而不是所需的
    O(logn)
    时间

    对于一棵树,您通常需要一棵平衡树,即一个节点的所有子节点理想情况下大小相同的树。在您的代码中,每个节点都有一个
    等级
    ,目标是在每个节点的左侧和右侧都有相同的等级。如果树中没有确切的
    2^n-1
    条目,这是不可能的,您必须允许树中存在一些不平衡。通常允许等级差为1或2。插入时应将元素插入秩较小的一侧,移除时必须重新平衡超出允许秩差的任何节点。这将保持树的合理平衡,确保保留所需的运行时属性

    检查你的课本,在你的情况下,等级上允许有什么不同

    module type Comparable = sig
        type t
        val compare : t -> t -> int
    end
    
    module LeftistHeap(Elem:Comparable) = struct
        exception Empty
        exception Same_elem
    
        type heap = E | T of int * Elem.t * heap * heap  
    
        let rank = function 
           | E -> 0
           | T (r ,_ ,_ ,_ ) -> r
    
        let makeT x a b =
           if rank a >= rank b
           then T(rank b + 1, x, a, b)
           else T(rank a + 1, x, b, a)
    
        let rec merge m n = match (m, n) with
           | (h, E) -> h
           | (E, h) -> h 
           | (T (_, x, a1, b1) as h1, (T (_, y, a2, b2) as h2)) ->
           if (Elem.compare x y) < 0
           then makeT x a1 (merge b1 h2)
           else makeT y a2 (merge b2 h1)
    
        let insert_merge x h = merge (T (1, x, E, E)) h
    
        let rec insert x t =
        try
            match t with
            | E -> T (1, x, E, E)
            | T (_, y, left, right ) ->
            match (Elem.compare x y) with
            | n when n < 0 -> makeT x left (insert y right)
            | 0 -> raise Same_elem
            | _ -> makeT y left (insert x right)
        with
            Same_elem -> t
    
        let rec creat_l_heap f = function 
            | [] -> E
            | h::t -> (f h (creat_l_heap f t))
    
        let create_merge l = creat_l_heap insert_merge l 
        let create_insert l = creat_l_heap insert l
    end;;
    
    module IntLeftTree = LeftistHeap(String);;
    
    open IntLeftTree;;
    
    let l = ["a";"b";"d";"g";"z";"e";"c"];;
    let lh = create_merge `enter code here`l;;
    let li = create_insert l;;
    
    let h = ["c";"e";"z";"g";"d";"b";"a"];;
    let hh = create_merge h;;
    let hi = create_insert h;;
    
    let rec insert x t =
      try
      match t with
      | E -> T (1, x, E, E)
      | T (_, y, left, right ) ->
        match (Elem.compare x y) with
        | n when n < 0 -> makeT x E t
        | 0 -> raise Same_elem
        | _ -> makeT y left (insert x right)
    with
      Same_elem -> t