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;
|
type T = BT::T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum BalancingError {
|
pub enum BalancingError {
|
||||||
LeafHeight(u64),
|
LeafHeight(u64),
|
||||||
NodeHeight,
|
NodeHeight,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
pub mod binary;
|
pub mod binary;
|
||||||
|
pub mod context;
|
||||||
|
|
||||||
use std::{error::Error, fmt::Display, rc::Rc};
|
use std::{error::Error, fmt::Display, rc::Rc};
|
||||||
|
|
||||||
|
use crate::flow::binary::balancing::*;
|
||||||
use crate::rcore::*;
|
use crate::rcore::*;
|
||||||
use crate::rstd::{
|
use crate::rstd::{
|
||||||
atomic::{au64::*, *},
|
atomic::{au64::*, *},
|
||||||
@ -14,11 +16,7 @@ pub enum AvlError<E> {
|
|||||||
Int(IntParseError),
|
Int(IntParseError),
|
||||||
Point(PointParseError),
|
Point(PointParseError),
|
||||||
Key(E),
|
Key(E),
|
||||||
LeafHeight(u64),
|
Balancing(BalancingError),
|
||||||
NodeHeight,
|
|
||||||
Balance(u64, u64),
|
|
||||||
HeightOverflow,
|
|
||||||
HeightMismatch { child: (u64, u64), parent: u64 },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> From<IntParseError> for AvlError<E> {
|
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> {
|
impl<E: Display> Display for AvlError<E> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -45,14 +49,8 @@ impl<E: Display> Display for AvlError<E> {
|
|||||||
Self::Key(key_error) => {
|
Self::Key(key_error) => {
|
||||||
write!(f, "failed to parse AVL node key: {key_error}")
|
write!(f, "failed to parse AVL node key: {key_error}")
|
||||||
}
|
}
|
||||||
Self::NodeHeight => write!(f, "invalid AVL non-leaf height: 0."),
|
Self::Balancing(balancing) => {
|
||||||
Self::LeafHeight(height) => {
|
write!(f, "balancing: {balancing}")
|
||||||
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}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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>> {
|
fn balanced<E>(hl: u64, hr: u64) -> Result<(), AvlError<E>> {
|
||||||
if std::cmp::max(hl, hr) - std::cmp::min(hl, hr) > 1 {
|
if std::cmp::max(hl, hr) - std::cmp::min(hl, hr) > 1 {
|
||||||
return Err(AvlError::Balance(hl, hr));
|
Err(BalancingError::Balance(hl, hr))?
|
||||||
}
|
}
|
||||||
Ok(())
|
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)?;
|
let height = u64::a_deserialize(deserializer)?;
|
||||||
if let Nullable::Null(_) = node {
|
if let Nullable::Null(_) = node {
|
||||||
if height != 0 {
|
if height != 0 {
|
||||||
return Err(AvlError::LeafHeight(height));
|
Err(BalancingError::LeafHeight(height))?
|
||||||
}
|
}
|
||||||
} else if height == 0 {
|
} else if height == 0 {
|
||||||
return Err(AvlError::NodeHeight);
|
Err(BalancingError::NodeHeight)?
|
||||||
}
|
}
|
||||||
Ok(AvlTree { node, height })
|
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> {
|
fn parent_height(&self) -> AvlResult<'a, Ctx, A, u64> {
|
||||||
std::cmp::max(self.l.height, self.r.height)
|
std::cmp::max(self.l.height, self.r.height)
|
||||||
.checked_add(1)
|
.checked_add(1)
|
||||||
.ok_or(AvlError::HeightOverflow)
|
.ok_or(AvlError::Balancing(BalancingError::HeightOverflow))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_tree(self) -> AvlTreeResult<'a, Ctx, A> {
|
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, ()> {
|
fn matches_height(&self, parent_height: u64) -> AvlResult<'a, Ctx, A, ()> {
|
||||||
let expected = self.parent_height()?;
|
let expected = self.parent_height()?;
|
||||||
if expected == parent_height {
|
if expected != parent_height {
|
||||||
Ok(())
|
Err(BalancingError::HeightMismatch {
|
||||||
} else {
|
children: (self.l.height, self.r.height),
|
||||||
Err(AvlError::HeightMismatch {
|
|
||||||
child: (self.l.height, self.r.height),
|
|
||||||
parent: parent_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