BalancedTrees
				
					
				
			This commit is contained in:
		
							parent
							
								
									d9c21f639d
								
							
						
					
					
						commit
						a897706a91
					
				@ -0,0 +1,105 @@
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
pub trait BinaryTreesUnbalanced<'a>: BinaryTreesHeight<'a> {
 | 
			
		||||
    fn tree_with_height(
 | 
			
		||||
        &self,
 | 
			
		||||
        tl: Self::Tree,
 | 
			
		||||
        key: Self::Key,
 | 
			
		||||
        tr: Self::Tree,
 | 
			
		||||
        height: u64,
 | 
			
		||||
    ) -> BTWrap<'a, Self, Self::Tree>;
 | 
			
		||||
 | 
			
		||||
    fn balancing_error<T: 'a>(&self, error: BalancingError) -> BTWrap<'a, Self, T>;
 | 
			
		||||
 | 
			
		||||
    fn balancing_bind<A: 'a, B: 'a>(
 | 
			
		||||
        &self,
 | 
			
		||||
        ra: Result<A, BalancingError>,
 | 
			
		||||
        f: impl FnOnce(A) -> BTWrap<'a, Self, B>,
 | 
			
		||||
    ) -> BTWrap<'a, Self, B> {
 | 
			
		||||
        match ra {
 | 
			
		||||
            Ok(a) => f(a),
 | 
			
		||||
            Err(e) => self.balancing_error(e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct BalancedTrees<BT>(BT);
 | 
			
		||||
 | 
			
		||||
impl<'a, BT: FunctorContext<'a>> FunctorContext<'a> for BalancedTrees<BT> {
 | 
			
		||||
    type T = BT::T;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum BalancingError {
 | 
			
		||||
    LeafHeight(u64),
 | 
			
		||||
    NodeHeight,
 | 
			
		||||
    Balance(u64, u64),
 | 
			
		||||
    HeightOverflow,
 | 
			
		||||
    HeightMismatch { children: (u64, u64), parent: u64 },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn balanced(hl: u64, hr: u64) -> Result<(), BalancingError> {
 | 
			
		||||
    if hl.abs_diff(hr) > 1 {
 | 
			
		||||
        Err(BalancingError::Balance(hl, hr))
 | 
			
		||||
    } else {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parent_height(hl: u64, hr: u64) -> Result<u64, BalancingError> {
 | 
			
		||||
    balanced(hl, hr)?;
 | 
			
		||||
    std::cmp::max(hl, hr)
 | 
			
		||||
        .checked_add(1)
 | 
			
		||||
        .ok_or(BalancingError::HeightOverflow)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn matches_height(hl: u64, hr: u64, hp: u64) -> Result<(), BalancingError> {
 | 
			
		||||
    if parent_height(hl, hr)? == hp {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    } else {
 | 
			
		||||
        Err(BalancingError::HeightMismatch {
 | 
			
		||||
            children: (hl, hr),
 | 
			
		||||
            parent: hp,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a, BT: BinaryTreesUnbalanced<'a>> BinaryTrees<'a> for BalancedTrees<BT> {
 | 
			
		||||
    type Node = BT::Node;
 | 
			
		||||
 | 
			
		||||
    type Reference = BT::Reference;
 | 
			
		||||
 | 
			
		||||
    type Tree = BT::Tree;
 | 
			
		||||
 | 
			
		||||
    type Key = BT::Key;
 | 
			
		||||
 | 
			
		||||
    type Comparator = BT::Comparator;
 | 
			
		||||
 | 
			
		||||
    type _Tm = Self::T;
 | 
			
		||||
 | 
			
		||||
    fn comparator(&self) -> &Self::Comparator {
 | 
			
		||||
        self.0.comparator()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn split(&self, node: &Self::Node) -> Split<'a, Self> {
 | 
			
		||||
        self.0.split(node)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node> {
 | 
			
		||||
        let hp = self.0.height_r(reference);
 | 
			
		||||
        let ctx = self.0.clone();
 | 
			
		||||
        Self::bind(self.0.resolve(reference), move |node| {
 | 
			
		||||
            let (tl, tr, _) = ctx.split(&node);
 | 
			
		||||
            let (hl, hr) = (ctx.height(&tl), ctx.height(&tr));
 | 
			
		||||
            ctx.balancing_bind(matches_height(hl, hr, hp), |_| Self::pure(node))
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn equal(&self, rl: &Self::Reference, rr: &Self::Reference) -> bool {
 | 
			
		||||
        self.0.height_r(rl) == self.0.height_r(rr) && self.0.equal(rl, rr)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn refer(&self, tree: &Self::Tree) -> Option<Self::Reference> {
 | 
			
		||||
        self.0.refer(tree)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user