mrds::trees::heighted

This commit is contained in:
AF 2023-06-16 17:29:54 +00:00
parent 20e441be04
commit ad6e381830
5 changed files with 298 additions and 5 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
/target
/Cargo.lock
**/*.rs.bk
metrics.ansi

View File

@ -1,4 +1,6 @@
use super::*;
use std::fmt::Display;
use super::{avl::*, bounds::bound::BinaryTreesBindable, *};
pub trait BinaryTreesUnbalanced<'a>: BinaryTreesHeight<'a> {
fn tree_of_with_height(&self, node: Self::Node, height: u64) -> BTWrap<'a, Self, Self::Tree>;
@ -25,6 +27,12 @@ pub trait BinaryTreesUnbalanced<'a>: BinaryTreesHeight<'a> {
#[derive(Clone)]
pub struct BalancedTrees<BT>(BT);
impl<BT> BalancedTrees<BT> {
pub fn new(bt: BT) -> Self {
Self(bt)
}
}
impl<'a, BT: FunctorContext<'a>> FunctorContext<'a> for BalancedTrees<BT> {
type T = BT::T;
}
@ -37,6 +45,25 @@ pub enum BalancingError {
HeightMismatch { children: (u64, u64), parent: u64 },
}
impl Display for BalancingError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
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 { children, parent } => {
write!(
f,
"AVL child-parent height mismatch: {children:?}, {parent}"
)
}
}
}
}
fn balanced(hl: u64, hr: u64) -> Result<(), BalancingError> {
if hl.abs_diff(hr) > 1 {
Err(BalancingError::Balance(hl, hr))
@ -151,3 +178,24 @@ impl<'a, BT: BinaryTreesUnbalanced<'a> + BinaryTreesTryJoin<'a>> BinaryTreesTryJ
.balancing_bind(balanced(hl, hr), |_| self.0.try_join(tl, key, tr))
}
}
impl<'a, BT: BinaryTreesUnbalanced<'a> + BinaryTreesBindable<'a>> BinaryTreesBindable<'a>
for BalancedTrees<BT>
{
fn bounds_error<T: 'a>(&self, error: bounds::BoundsError<Self::Key>) -> BTWrap<'a, Self, T> {
self.0.bounds_error(error)
}
}
impl<'a, BT: BinaryTreesUnbalanced<'a> + BinaryTreesEmpty<'a> + BinaryTreesTryJoin<'a>>
BinaryTreesMutable<'a> for BalancedTrees<BT>
{
fn join_key(
self,
tl: Self::Tree,
key: Self::Key,
tr: Self::Tree,
) -> BTWrap<'a, Self, Self::Node> {
self.join_key_balanced(tl, key, tr)
}
}

View File

@ -1,2 +1,3 @@
pub mod avl;
pub mod heighted;
pub mod unbalanced;

View File

@ -1,7 +1,7 @@
use std::{fmt::Display, marker::PhantomData, rc::Rc};
use crate::flow::{
binary::{avl::*, bounds::bound::BinaryTreesBindable, *},
binary::{avl::*, bounds::bound::*, *},
comparator::*,
};
use crate::func::{context::*, *};
@ -199,14 +199,12 @@ impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesTryJoin<'a> for AvlTs<A> {
impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesBindable<'a> for AvlTs<A> {
fn bounds_error<T: 'a>(&self, _error: bounds::BoundsError<Self::Key>) -> BTWrap<'a, Self, T> {
panic!("bounds violated");
panic!("bounds violated.");
}
}
#[cfg(test)]
mod tests {
use crate::flow::binary::bounds::bound::*;
use super::*;
#[test]

245
src/mrds/trees/heighted.rs Normal file
View File

@ -0,0 +1,245 @@
use std::{fmt::Display, marker::PhantomData, rc::Rc};
use crate::flow::{
binary::{balancing::*, bounds::bound::*, *},
comparator::*,
};
use crate::func::{context::*, *};
#[derive(Clone)]
struct Node<A> {
l: Tree<A>,
r: Tree<A>,
key: A,
}
impl<A: Display> Display for Node<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({} {} {})", self.l, self.key, self.r)
}
}
struct Reference<A> {
node: Rc<Node<A>>,
}
impl<A> Clone for Reference<A> {
fn clone(&self) -> Self {
Self {
node: self.node.clone(),
}
}
}
impl<A: Display> Display for Reference<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.node)
}
}
struct Tree<A> {
reference: Option<Reference<A>>,
height: u64,
}
impl<A> Clone for Tree<A> {
fn clone(&self) -> Self {
Self {
reference: self.reference.clone(),
height: self.height,
}
}
}
impl<A: Display> Display for Tree<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.reference {
Some(reference) => write!(f, "{}", reference),
None => write!(f, "-"),
}
}
}
struct Trees<A> {
_a: PhantomData<A>,
}
impl<A> Trees<A> {
fn new() -> Self {
Self { _a: PhantomData }
}
}
impl<A> Clone for Trees<A> {
fn clone(&self) -> Self {
Self::new()
}
}
impl<'a, A: 'a> FunctorContext<'a> for Trees<A> {
type T = instances::solo::SoloInstance;
}
impl<'a, A: 'a + PartialOrd + Clone> BinaryTrees<'a> for Trees<A> {
type Node = Node<A>;
type Reference = Reference<A>;
type Tree = Tree<A>;
type Key = A;
type Comparator = DefaultComparator;
type _Tm = Self::T;
fn comparator(&self) -> &Self::Comparator {
&DefaultComparator
}
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> {
reference.node.as_ref().clone()
}
fn equal(&self, _rhs: &Self::Reference, _lhs: &Self::Reference) -> bool {
false
}
fn refer(&self, tree: &Self::Tree) -> Option<Self::Reference> {
tree.reference.clone()
}
}
impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesHeight<'a> for Trees<A> {
fn height(&self, tree: &Self::Tree) -> u64 {
tree.height
}
fn leaf_height_error<T: 'a>(&self, height: u64) -> BTWrap<'a, Self, T> {
panic!("leaf height error: {height}.")
}
}
impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesEmpty<'a> for Trees<A> {
fn empty(&self) -> Self::Tree {
Tree {
reference: None,
height: 0,
}
}
fn split_key_empty(
&self,
_tree: Self::Tree,
_key: Self::Key,
) -> BTWrap<'a, Self, KeySplit<'a, Self>> {
(self.empty(), self.empty())
}
}
impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesTryJoin<'a> for Trees<A> {
fn try_join(
&self,
tl: Self::Tree,
key: Self::Key,
tr: Self::Tree,
) -> BTWrap<'a, Self, Self::Node> {
Node { l: tl, r: tr, key }
}
}
impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesUnbalanced<'a> for Trees<A> {
fn tree_of_with_height(&self, node: Self::Node, height: u64) -> BTWrap<'a, Self, Self::Tree> {
Tree {
reference: Some(Reference {
node: Rc::new(node),
}),
height,
}
}
fn balancing_error<T: 'a>(&self, _error: BalancingError) -> BTWrap<'a, Self, T> {
panic!("balancing error.")
}
}
impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesBindable<'a> for Trees<A> {
fn bounds_error<T: 'a>(&self, _error: bounds::BoundsError<Self::Key>) -> BTWrap<'a, Self, T> {
panic!("bounds violated.");
}
}
#[cfg(test)]
mod tests {
use super::*;
impl<A> Node<A> {
fn balanced(&self) -> bool {
let (hl, hr) = (self.l.height, self.r.height);
std::cmp::max(hl, hr) - std::cmp::min(hl, hr) < 2
&& self.l.balanced()
&& self.r.balanced()
}
}
impl<A> Reference<A> {
fn balanced(&self) -> bool {
self.node.balanced()
}
}
impl<A> Tree<A> {
fn balanced(&self) -> bool {
match &self.reference {
Some(reference) => reference.balanced(),
None => true,
}
}
}
#[test]
fn test() {
let trees = BalancedTrees::new(Trees::new());
let mut tree = trees.empty();
for i in [
8, 3, 10, 17, 0, 13, 6, 1, 11, 5, 4, 7, 18, 14, 15, 9, 2, 19, 16, 12,
] {
tree = trees.clone().add_tree(tree, i);
assert!(tree.balanced());
// println!("{} {}", tree.height, tree);
}
for i in [
2, 9, 4, 7, 8, 10, 17, 1, 13, 15, 18, 12, 5, 0, 3, 6, 16, 19, 14, 11,
] {
tree = trees.clone().remove(tree, i);
assert!(tree.balanced());
// println!("{} {}", tree.height, tree);
}
// assert!(false);
}
#[test]
fn test_with_bounds() {
let trees = BoundTrees::new(BalancedTrees::new(Trees::new()));
let mut tree = trees.empty();
for i in [
8, 3, 10, 17, 0, 13, 6, 1, 11, 5, 4, 7, 18, 14, 15, 9, 2, 19, 16, 12,
] {
tree = trees.clone().add_tree(tree, i);
assert!(tree.balanced());
// println!("{} {}", tree.height, tree);
}
for i in [
2, 9, 4, 7, 8, 10, 17, 1, 13, 15, 18, 12, 5, 0, 3, 6, 16, 19, 14, 11,
] {
tree = trees.clone().remove(tree, i);
assert!(tree.balanced());
// println!("{} {}", tree.height, tree);
}
// assert!(false);
}
}