AvlTrees
This commit is contained in:
parent
8770541035
commit
c1f48b1c08
@ -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,
|
||||
|
@ -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 })
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
71
src/rstd/collections/avl/context.rs
Normal file
71
src/rstd/collections/avl/context.rs
Normal 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()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user