mirror of
https://github.com/Noratrieb/datastructures.git
synced 2026-01-14 17:35:02 +01:00
almost works
This commit is contained in:
parent
04d0aaab72
commit
7eb2aceb63
2 changed files with 172 additions and 0 deletions
169
src/binary_tree.rs
Normal file
169
src/binary_tree.rs
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
struct BinaryTree<T>(Node<T>);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Node<T> {
|
||||||
|
lhs: Option<Box<Node<T>>>,
|
||||||
|
val: T,
|
||||||
|
rhs: Option<Box<Node<T>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Node<T> {
|
||||||
|
pub fn new(value: T, lhs: Option<Node<T>>, rhs: Option<Node<T>>) -> Self {
|
||||||
|
Self {
|
||||||
|
lhs: lhs.map(Box::new),
|
||||||
|
val: value,
|
||||||
|
rhs: rhs.map(Box::new),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leaf(value: T) -> Self {
|
||||||
|
Self::new(value, None, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DisplayTree {
|
||||||
|
fn depth(&self) -> usize;
|
||||||
|
fn offset_x(&self) -> usize;
|
||||||
|
fn amount_of_con(&self) -> usize;
|
||||||
|
fn display(&self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display> DisplayTree for Node<T> {
|
||||||
|
fn depth(&self) -> usize {
|
||||||
|
self.lhs
|
||||||
|
.as_ref()
|
||||||
|
.map(|node| node.depth() + 1)
|
||||||
|
.unwrap_or(0)
|
||||||
|
.max(self.rhs.as_ref().map(|node| node.depth() + 1).unwrap_or(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset_x(&self) -> usize {
|
||||||
|
let offset_below = self.lhs.as_ref().map(|node| node.offset_x()).unwrap_or(0);
|
||||||
|
let depth = self.depth();
|
||||||
|
|
||||||
|
if depth == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_below + self.amount_of_con() + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn amount_of_con(&self) -> usize {
|
||||||
|
let depth = self.depth();
|
||||||
|
if depth == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
2_usize.pow((depth - 1) as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display(&self) -> String {
|
||||||
|
let mut str = String::new();
|
||||||
|
|
||||||
|
let offset_x = self.offset_x();
|
||||||
|
|
||||||
|
// top level
|
||||||
|
|
||||||
|
str.push_str(&".".repeat(offset_x));
|
||||||
|
str.push_str(&self.val.to_string());
|
||||||
|
str.push('\n');
|
||||||
|
|
||||||
|
for i in 0..self.amount_of_con() {
|
||||||
|
str.push_str(&".".repeat(offset_x - i - 1));
|
||||||
|
str.push('/');
|
||||||
|
str.push_str(&".".repeat(1 + 2 * i));
|
||||||
|
str.push('\\');
|
||||||
|
str.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// rest
|
||||||
|
// let mut next_nodes = vec![];
|
||||||
|
let mut current_nodes = vec![&self.lhs, &self.rhs]
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
while current_nodes.len() > 0 {
|
||||||
|
// display node layer
|
||||||
|
|
||||||
|
for (i, node) in current_nodes.iter().enumerate() {
|
||||||
|
// print node values
|
||||||
|
str.push_str(&".".repeat(node.offset_x()));
|
||||||
|
str.push_str(&node.val.to_string());
|
||||||
|
if i != current_nodes.len() - 1 {
|
||||||
|
str.push_str(&".".repeat(node.offset_x() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push('\n');
|
||||||
|
// print node connections
|
||||||
|
|
||||||
|
let mut offset = 0;
|
||||||
|
let nodes_with_offset = current_nodes
|
||||||
|
.iter()
|
||||||
|
.map(|node| {
|
||||||
|
offset += node.offset_x();
|
||||||
|
let this_offset = offset;
|
||||||
|
offset += node.val.to_string().len();
|
||||||
|
offset += node.offset_x() + 1;
|
||||||
|
(this_offset, node)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let amount_of_con = current_nodes
|
||||||
|
.first()
|
||||||
|
.map(|node| node.amount_of_con())
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
for i in 0..amount_of_con {
|
||||||
|
let mut connections = nodes_with_offset
|
||||||
|
.iter()
|
||||||
|
.map(|(offset, _)| (offset - 1 - i, '/'))
|
||||||
|
.chain(
|
||||||
|
nodes_with_offset
|
||||||
|
.iter()
|
||||||
|
.map(|(offset, _)| (offset + 1 + i, '\\')),
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
connections.sort_by(|(a_offset, _), (b_offset, _)| a_offset.cmp(b_offset));
|
||||||
|
|
||||||
|
let mut prev_offset = 0;
|
||||||
|
for (offset, con) in connections {
|
||||||
|
let diff_offset = offset - prev_offset;
|
||||||
|
str.push_str(&".".repeat(diff_offset));
|
||||||
|
str.push(con);
|
||||||
|
prev_offset += diff_offset + 1;
|
||||||
|
}
|
||||||
|
str.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
current_nodes = current_nodes
|
||||||
|
.into_iter()
|
||||||
|
.map(|node| [&node.lhs, &node.rhs])
|
||||||
|
.flatten()
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test {
|
||||||
|
use crate::binary_tree::{DisplayTree, Node};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn print_cool_tree() {
|
||||||
|
let tree = Node::new(
|
||||||
|
4,
|
||||||
|
Some(Node::new(2, Some(Node::leaf(1)), Some(Node::leaf(3)))),
|
||||||
|
Some(Node::new(6, Some(Node::leaf(5)), Some(Node::leaf(7)))),
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("{}", tree.display());
|
||||||
|
|
||||||
|
panic!("fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,3 +3,6 @@ pub mod linked_list;
|
||||||
|
|
||||||
/// A packed doubly linked list
|
/// A packed doubly linked list
|
||||||
pub mod packed_linked_list;
|
pub mod packed_linked_list;
|
||||||
|
|
||||||
|
/// A binary tree that can be printed
|
||||||
|
mod binary_tree;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue