cp_library_rs/tree/
show_binary_tree.rs

1//! 2分木を整形して表示する
2
3const LEFT: &str = "  ┌─";
4const MID: &str = "  │ ";
5const RIGHT: &str = "  └─";
6const NULL: &str = "";
7const BLANK: &str = "    ";
8
9/// 2分木を整形して表示する
10pub trait ShowBinaryTree<P> {
11    /// **\<required\>** 左の子のポインタを取得する
12    fn get_left(&self, ptr: &P) -> Option<P>;
13
14    /// **\<required\>** 右の子のポインタを取得する
15    fn get_right(&self, ptr: &P) -> Option<P>;
16
17    /// **\<required\>** 根を取得する
18    fn get_root(&self) -> Option<P>;
19
20    /// **\<required\>** ノードの値を表示する
21    fn print_node(&self, ptr: &P) -> String;
22
23    /// 再帰的にprintを行う
24    fn print_inner(&self, ptr: P, fill: &mut Vec<&'static str>, last: &'static str) {
25        // 表示の調整
26        let mut tmp = None;
27        if fill.last().is_some_and(|x| x == &last) {
28            tmp = fill.pop();
29            fill.push(BLANK);
30        } else if fill.last().is_some_and(|x| x != &NULL && x != &BLANK) {
31            tmp = fill.pop();
32            fill.push(MID);
33        }
34        fill.push(last);
35
36        // 右の子を表示
37        if let Some(left) = Self::get_left(self, &ptr) {
38            self.print_inner(left, fill, LEFT);
39        }
40
41        // 自分を出力
42        eprintln!("│{} {}", fill.join(""), self.print_node(&ptr));
43
44        // 右の子を表示
45        if let Some(right) = Self::get_right(self, &ptr) {
46            self.print_inner(right, fill, RIGHT);
47        }
48
49        // 戻す
50        fill.pop();
51        if let Some(tmp) = tmp {
52            fill.pop();
53            fill.push(tmp);
54        }
55    }
56
57    /// 2分木としてフォーマットする
58    fn print_as_binary_tree(&self) {
59        #[cfg(debug_assertions)]
60        {
61            eprintln!("┌───────────────────────────────────────────────────────");
62            if let Some(root) = Self::get_root(self) {
63                Self::print_inner(self, root, &mut vec![], NULL);
64            }
65            eprintln!("└───────────────────────────────────────────────────────");
66        }
67    }
68}