This commit is contained in:
AF 2023-06-17 03:53:40 +00:00
parent 8770541035
commit c1f48b1c08
4 changed files with 92 additions and 23 deletions

View File

@ -37,6 +37,7 @@ impl<'a, BT: FunctorContext<'a>> FunctorContext<'a> for BalancedTrees<BT> {
type T = BT::T;
}
#[derive(Debug)]
pub enum BalancingError {
LeafHeight(u64),
NodeHeight,

View File

@ -1,7 +1,9 @@
pub mod binary;
pub mod context;
use std::{error::Error, fmt::Display, rc::Rc};
use crate::flow::binary::balancing::*;
use crate::rcore::*;
use crate::rstd::{
atomic::{au64::*, *},
@ -14,11 +16,7 @@ pub enum AvlError<E> {
Int(IntParseError),
Point(PointParseError),
Key(E),
LeafHeight(u64),
NodeHeight,
Balance(u64, u64),
HeightOverflow,
HeightMismatch { child: (u64, u64), parent: u64 },
Balancing(BalancingError),
}
impl<E> From<IntParseError> for AvlError<E> {
@ -33,6 +31,12 @@ impl<E> From<PointParseError> for AvlError<E> {
}
}
impl<E> From<BalancingError> for AvlError<E> {
fn from(value: BalancingError) -> Self {
Self::Balancing(value)
}
}
impl<E: Display> Display for AvlError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
@ -45,14 +49,8 @@ impl<E: Display> Display for AvlError<E> {
Self::Key(key_error) => {
write!(f, "failed to parse AVL node key: {key_error}")
}
Self::NodeHeight => write!(f, "invalid AVL non-leaf height: 0."),
Self::LeafHeight(height) => {
write!(f, "invalid AVL leaf height: {height}!=0.")
}
Self::Balance(hl, hr) => write!(f, "unbalanced AVL node: {hl} {hr}."),
Self::HeightOverflow => write!(f, "AVL tree height overflow"),
Self::HeightMismatch { child, parent } => {
write!(f, "AVL child-parent height mismatch: {child:?}, {parent}")
Self::Balancing(balancing) => {
write!(f, "balancing: {balancing}")
}
}
}
@ -120,7 +118,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Avl
fn balanced<E>(hl: u64, hr: u64) -> Result<(), AvlError<E>> {
if std::cmp::max(hl, hr) - std::cmp::min(hl, hr) > 1 {
return Err(AvlError::Balance(hl, hr));
Err(BalancingError::Balance(hl, hr))?
}
Ok(())
}
@ -175,10 +173,10 @@ impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> Factory<'a, Ctx> for AvlTreeFact
let height = u64::a_deserialize(deserializer)?;
if let Nullable::Null(_) = node {
if height != 0 {
return Err(AvlError::LeafHeight(height));
Err(BalancingError::LeafHeight(height))?
}
} else if height == 0 {
return Err(AvlError::NodeHeight);
Err(BalancingError::NodeHeight)?
}
Ok(AvlTree { node, height })
}

View File

@ -23,7 +23,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> AvlNode<'a, Ctx, A> {
fn parent_height(&self) -> AvlResult<'a, Ctx, A, u64> {
std::cmp::max(self.l.height, self.r.height)
.checked_add(1)
.ok_or(AvlError::HeightOverflow)
.ok_or(AvlError::Balancing(BalancingError::HeightOverflow))
}
pub fn into_tree(self) -> AvlTreeResult<'a, Ctx, A> {
@ -43,14 +43,13 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> AvlNode<'a, Ctx, A> {
fn matches_height(&self, parent_height: u64) -> AvlResult<'a, Ctx, A, ()> {
let expected = self.parent_height()?;
if expected == parent_height {
Ok(())
} else {
Err(AvlError::HeightMismatch {
child: (self.l.height, self.r.height),
if expected != parent_height {
Err(BalancingError::HeightMismatch {
children: (self.l.height, self.r.height),
parent: parent_height,
})
})?
}
Ok(())
}
}

View File

@ -0,0 +1,71 @@
use std::marker::PhantomData;
use crate::{
flow::{binary::*, comparator::*},
func::context::*,
rstd::fallible::*,
};
use super::{binary::*, *};
struct AvlTrees<C, T>(Rc<C>, PhantomData<T>);
impl<C, T> AvlTrees<C, T> {
fn new(comparator: Rc<C>) -> Self {
Self(comparator, PhantomData)
}
}
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone, C: 'a + Comparator<A>> Clone
for AvlTrees<C, (Ctx, A)>
{
fn clone(&self) -> Self {
Self::new(self.0.clone())
}
}
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone, C: 'a + Comparator<A>>
FunctorContext<'a> for AvlTrees<C, (Ctx, A)>
{
type T = FallibleMonad<
'a,
Ctx,
ResolutionError<Ctx::LookupError, AvlError<ParseError<'a, Ctx, Fctr<'a, Ctx, A>>>>,
>;
}
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone, C: 'a + Comparator<A>> BinaryTrees<'a>
for AvlTrees<C, (Ctx, A)>
{
type Node = AvlNode<'a, Ctx, A>;
type Reference = AvlReference<'a, Ctx, A>;
type Tree = AvlTree<'a, Ctx, A>;
type Key = A;
type Comparator = C;
type _Tm = Self::T;
fn comparator(&self) -> &Self::Comparator {
&self.0
}
fn split(&self, node: &Self::Node) -> Split<'a, Self> {
(node.l.clone(), node.r.clone(), node.key.clone())
}
fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node> {
Self::fmap(Ctx::stuff(reference.resolve()), |rc| rc.as_ref().clone())
}
fn equal(&self, rl: &Self::Reference, rr: &Self::Reference) -> bool {
rl == rr
}
fn refer(&self, tree: &Self::Tree) -> Option<Self::Reference> {
tree.reference()
}
}