use std::{fmt::Display, mem::swap};
use crate::DisplayableNode;
pub struct BinaryTree<D> {
data: D,
children: [Option<Box<BinaryTree<D>>>; 2],
}
#[macro_export]
macro_rules! bt {
(
$value:expr,
$left:expr,
$right:expr
) => {{
BinaryTree::assemble(($value), Some($left), Some($right))
}};
(
$value:expr,
,
$right:expr
) => {{
BinaryTree::assemble(($value), None, Some($right))
}};
(
$value:expr,
$left:expr,
) => {{
BinaryTree::assemble(($value), Some($left), None)
}};
(
$value:expr
) => {{
BinaryTree::new(($value))
}};
}
impl<D> BinaryTree<D> {
pub fn new(data: D) -> Self {
Self {
data,
children: [None, None],
}
}
pub fn assemble(data: D, x: Option<BinaryTree<D>>, y: Option<BinaryTree<D>>) -> Self {
let x = x.map(|x| Box::new(x));
let y = y.map(|y| Box::new(y));
Self {
data,
children: [x, y],
}
}
pub fn children(&self) -> (Option<&BinaryTree<D>>, Option<&BinaryTree<D>>) {
let [x, y] = &self.children;
let x = x.as_ref().map(|boxed_x| boxed_x.as_ref());
let y = y.as_ref().map(|boxed_y| boxed_y.as_ref());
(x, y)
}
pub fn x_ref(&self) -> Option<&BinaryTree<D>> {
self.children[0].as_ref().map(|boxed| boxed.as_ref())
}
pub fn y_ref(&self) -> Option<&BinaryTree<D>> {
self.children[1].as_ref().map(|boxed| boxed.as_ref())
}
pub fn x_mut(&mut self) -> Option<&mut BinaryTree<D>> {
self.children[0].as_mut().map(|boxed| boxed.as_mut())
}
pub fn y_mut(&mut self) -> Option<&mut BinaryTree<D>> {
self.children[1].as_mut().map(|boxed| boxed.as_mut())
}
pub fn set_x(&mut self, x: BinaryTree<D>) -> Option<BinaryTree<D>> {
let mut outer = Some(Box::new(x));
let outer_ref = &mut outer;
let inner_ref = &mut self.children[0];
swap(outer_ref, inner_ref);
outer.map(|boxed| *boxed)
}
pub fn set_y(&mut self, y: BinaryTree<D>) -> Option<BinaryTree<D>> {
let mut outer = Some(Box::new(y));
let outer_ref = &mut outer;
let inner_ref = &mut self.children[1];
swap(outer_ref, inner_ref);
outer.map(|boxed| *boxed)
}
pub fn data(&self) -> &D {
&self.data
}
pub fn data_put(&mut self) -> &mut D {
&mut self.data
}
}
impl<D: Display> DisplayableNode for BinaryTree<D> {
fn label(&self) -> Option<String> {
let data = self.data();
Some(format!("{data}"))
}
fn children(&self) -> Vec<&Self> {
match self.children() {
(Some(left), Some(right)) => vec![left, right],
(Some(left), None) => vec![left],
(None, Some(right)) => vec![right],
(None, None) => vec![],
}
}
}
#[test]
fn it_works() {
let tree = bt!(
1,
bt!(
2,
,
bt!(5)
),
bt!(3, bt!(4, bt!(7),), bt!(6))
);
println!("{}", tree.display());
}