// Complete Binary Tree โ 99 Problems #34
// Construct a complete binary tree with n nodes.
// A complete binary tree fills levels left-to-right.
#[derive(Debug, PartialEq, Clone)]
enum Tree<T> {
Leaf,
Node(Box<Tree<T>>, T, Box<Tree<T>>),
}
impl<T: Clone> Tree<T> {
fn leaf() -> Self { Tree::Leaf }
fn node(l: Tree<T>, v: T, r: Tree<T>) -> Self {
Tree::Node(Box::new(l), v, Box::new(r))
}
fn size(&self) -> usize {
match self {
Tree::Leaf => 0,
Tree::Node(l, _, r) => 1 + l.size() + r.size(),
}
}
}
/// Build a complete binary tree with n nodes, values 1..=n.
/// Uses the property: node i has left child 2i and right child 2i+1.
fn complete_binary_tree(n: usize) -> Tree<usize> {
build(1, n)
}
fn build(pos: usize, n: usize) -> Tree<usize> {
if pos > n {
Tree::leaf()
} else {
Tree::node(build(2 * pos, n), pos, build(2 * pos + 1, n))
}
}
/// Check whether a binary tree is complete.
fn is_complete<T>(tree: &Tree<T>) -> bool {
fn check<T>(tree: &Tree<T>, pos: usize, n: usize) -> bool {
match tree {
Tree::Leaf => true,
Tree::Node(l, _, r) => {
pos <= n && check(l, 2 * pos, n) && check(r, 2 * pos + 1, n)
}
}
}
fn size<T>(t: &Tree<T>) -> usize {
match t {
Tree::Leaf => 0,
Tree::Node(l, _, r) => 1 + size(l) + size(r),
}
}
let n = size(tree);
check(tree, 1, n)
}
fn main() {
for n in [0, 1, 3, 4, 7, 8] {
let t = complete_binary_tree(n);
println!("n={}: size={}, complete={}", n, t.size(), is_complete(&t));
}
let t = complete_binary_tree(6);
println!("Tree(6): {:?}", t);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_size_matches() {
for n in 0..=10 {
assert_eq!(complete_binary_tree(n).size(), n);
}
}
#[test]
fn test_is_complete() {
for n in 0..=10 {
assert!(is_complete(&complete_binary_tree(n)), "n={} not complete", n);
}
}
#[test]
fn test_incomplete_tree_detected() {
// A right-heavy chain is not complete for n >= 2
let t = Tree::node(
Tree::leaf(),
1,
Tree::node(Tree::leaf(), 2, Tree::leaf()),
);
assert!(!is_complete(&t));
}
}
(* Complete Tree *)
(* OCaml 99 Problems #34 *)
(* Implementation for example 34 *)
(* Tests *)
let () =
(* Add tests *)
print_endline "โ OCaml tests passed"