Braun Tree及相关操作(ML 实现)

Braun Tree

基本定义

这里仅给出Binary Braun Tree定义(多叉树理论上可以此类推,emm):
一个二叉树是Braun Tree当且仅当它满足以下性质

  • 它是空树
  • 或者它的左子树和右子树均为Braun Tree
  • 左右子树节点数 N l , N r N_l,N_r Nl,Nr(简记为 ∣ L ∣ , ∣ R ∣ |L|,|R| L,R)满足 ∣ R ∣ ≤ ∣ L ∣ ≤ ∣ R ∣ + 1 |R|\le |L|\le |R|+1 RLR+1

其中第三点对于Braun良好的平衡性以及操作的简洁高效有着至关重要的意义,且下面的操作几乎均基于这一性质有关,是理解Braun Tree的关键。


braun tree实现的弹性数组(flexiable array based on Braun Tree)

braun tree本身对节点顺序(序号)并无要求,但是我们用如下形式给braun tree的节点编号,可以很好地组织braun tree。
braun tree

数据类型

使用最简单的结构

datatype a' tree = Lf
				 | Br of a'*a' tree*a' tree 
基本操作(及理解)
  1. sub
fun sub(Lf, _) = raise Subsrcipt
  | sub(Br(v, tl, tr), k) = 
    if k = 1 then v
    else if k mod 2 = 0 
    	 then sub(tl, k div 2)
    	 else sub(tr, k div 2)

理解:按上图,它的组织方式类似哈夫曼编码,第h层的序号均为长h(前缀0不计入长度,或者说首位必为1)的二进制串。对于 k = ( a h a h − 1 … a 1 a 0 ) 2 k=(a_ha_{h-1}\ldots a_1a_0)_2 k=(ahah1a1a0)2,从低位到高位按照 a i a_i ai的值决定路径, a i = 0 a_i=0 ai=0(即 k m o d    2 = 0 k \mod 2 = 0 kmod2=0)向左子树走, a i = 1 ( k m o d    2 = 1 ) a_i=1(k\mod 2 =1 ) ai=1(kmod2=1)向右子树走。

  1. update
  2. delete
  3. loext(从根处扩展数组)
fun loext(Lf, w) = Br(w, Lf, Lf)
  | loext(Br(v, tl, tr), w) = 
    Br(w, loext(tr, v), tl)

理解

  • low extend 从低处扩展,即从根部插入节点扩展弹性数组
  • 直观描述算法
    原根节点 1 → 2 1\rightarrow 2 12,应放入2号位置;原左子树 ( 2 , 4 , 6 , … ) (2,4,6,\ldots) (2,4,6,)序号 + 1 +1 +1后变为 ( 3 , 5 , 6 , … ) (3,5,6,\ldots) (3,5,6,),直接变为扩展后的右子树;扩展后左子树显然变为新的相同的子问题,即将原根节点 ( 1 → 2 ) (1\rightarrow 2) (12)扩展到原右子树上。
    (为什么说子问题是相同的?注意到原每个子树都是braun tree,那么原右子树一定是braun tree)
    在这里插入图片描述
  • 保Braun tree性(即扩展后的树仍然为Braun Tree)
    既然从低处扩展数组,那么应该将根节点下沉,由于Braun Tree的性质要求 ∣ R ∣ ≤ ∣ L ∣ ≤ ∣ R ∣ + 1 |R|\leq |L|\le |R|+1 RLR+1,将根节点沉入右子树,此时满足
    ∣ L ∣ ≤ ∣ R ′ ∣ ≤ ∣ L ∣ + 1 ( ∣ R ′ ∣ = ∣ R ∣ + 1 ) |L|\le |R'|\le|L|+1(|R'|=|R|+1) LRL+1(R=R+1)
  • high extend
    从高处扩展Braun Tree,其实和loext几乎完全相同,唯一的区别就是下沉的不是原节点而是插入节点
fun hiext(Lf, w) = Br(w, Lf, Lf)
  | hiext(Br(v, tl, tr), w) = 
    Br(v, hiext(tr, w), tl)
  1. lorem
    理解:loext 的逆过程,形象地描述为“上浮”过程,不再赘述;hirem 同理。
  2. length(count函数)
    一般来说,计算树的节点个数只需把每个节点遍历一遍即可,花费 O ( n ) O(n) O(n)时间。但在 B r a u n Braun Braun T r e e Tree Tree中却可以达到 O ( l o g n ) O(logn) O(logn)
fun diff Br(_, Lf, Lf) 0 = 0
  | diff Br(_, Lf, Lf) 1 = 1
  | diff Br(_, tl, tr) n = 
    if n mod 2 = 1 then diff tl (n div 2)
    else diff tr (n div 2)
    
fun length Lf = 0
  | length Br(_, Lf, Lf) = 1
  | length Br(_, tl, tr) = 
    let val nl = length tr
    in 1+2*nl+(diff tl nl) end

理解
Braun Tree重要性质 ∣ R ∣ ≤ ∣ L ∣ ≤ ∣ R ∣ + 1 → ∣ L ∣ = ∣ R ∣  or  ∣ R ∣ + 1 |R|\le|L|\le|R|+1\rightarrow |L|=|R|\text{ or }|R|+1 RLR+1L=R or R+1
只需计算其中一个子树的节点数 m m m然后总节点数最多等于 1 + 2 ∗ m 1+2*m 1+2m再加上1,这由 ∣ L ∣ |L| L是等于 ∣ R ∣ |R| R还是 ∣ R ∣ + 1 |R|+1 R+1决定,于是我们定义一个函数diff,它返回1当 ∣ L ∣ = ∣ R ∣ |L|=|R| L=R,否则返回0。
这样可以得到树t的节点个数为

     length t as Br(r, tl, tr) = 1 + 2*m + (diff tl m)

下面给出diff的递推式:
在这里插入图片描述

假设 t = B r ( r , t l , t r ) , t l = B r ( r 1 , l 1 , r 1 ) , t r t=Br(r,t_l,t_r),t_l=Br(r_1,l_1,r_1),t_r t=Br(r,tl,tr),tl=Br(r1,l1,r1),tr
其中 ∣ t r ∣ = m |t_r|=m tr=m,再根据Braun Tree性质 ∣ R ∣ ≤ ∣ L ∣ ≤ ∣ R ∣ + 1 |R|\le|L|\le|R|+1 RLR+1
可知 ∣ t l ∣ = m  或  m + 1 |t_l|=m\text{ 或 }m+1 tl=m  m+1,对 m m m分奇偶讨论:

  • m = 2 k + 1 m=2k+1 m=2k+1时,如上图根 r 1 r_1 r1的树,无论 ∣ t l ∣ = m 还 是 m + 1 |t_l|=m还是m+1 tl=mm+1,其右子树节点个数 ∣ r 1 ∣ |r_1| r1均为 k k k,于是可知,要判断是否有 ∣ t l ∣ = m |t_l|=m tl=m,关键是判断是否有 ∣ l 1 ∣ = k |l_1|=k l1=k,代码表示为
    diff tl 2k+1 = diff l1 k 
  • m = 2 k + 2 m=2k+2 m=2k+2时,如上图根 r 2 r_2 r2的树,分析过程几乎奇数时相同,此时 t t t的左子树的节点个数 ∣ l 1 ∣ |l_1| l1均为 k + 1 k+1 k+1,判断依据用代码表示
    diff tl 2k+2 = diff r1 k+1 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值