Task: Visualize a tree


C++: #include <functional>
#include <iostream>
#include <random>

class BinarySearchTree {
private:
    struct Node {
        int key;
        Node *left, *right;

        Node(int k) : key(k), left(nullptr), right(nullptr) {
            
        }
    } *root;

public:
    BinarySearchTree() : root(nullptr) {
        
    }

    bool insert(int key) {
        if (root == nullptr) {
            root = new Node(key);
        } else {
            auto n = root;
            Node *parent;
            while (true) {
                if (n->key == key) {
                    return false;
                }

                parent = n;

                bool goLeft = key < n->key;
                n = goLeft ? n->left : n->right;

                if (n == nullptr) {
                    if (goLeft) {
                        parent->left = new Node(key);
                    } else {
                        parent->right = new Node(key);
                    }
                    break;
                }
            }
        }
        return true;
    }

    friend std::ostream &operator<<(std::ostream &, const BinarySearchTree &);
};

template<typename T>
void display(std::ostream &os, const T *n) {
    if (n != nullptr) {
        os << "Node(";

        display(os, n->left);

        os << ',' << n->key << ',';

        display(os, n->right);

        os << ")";
    } else {
        os << '-';
    }
}

std::ostream &operator<<(std::ostream &os, const BinarySearchTree &bst) {
    display(os, bst.root);
    return os;
}

int main() {
    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(0, 200);
    auto rng = std::bind(distribution, generator);

    BinarySearchTree tree;

    tree.insert(100);
    for (size_t i = 0; i < 20; i++) {
        tree.insert(rng());
    }
    std::cout << tree << '\n';

    return 0;
}


C#: using System;

public static class VisualizeTree
{
    public static void Main() {
        "A".t(
            "B0".t(
                "C1",
                "C2".t(
                    "D".t("E1", "E2", "E3")),
                "C3".t(
                    "F1",
                    "F2",
                    "F3".t("G"),
                    "F4".t("H1", "H2"))),
            "B1".t(
                "K1",
                "K2".t(
                    "L1".t("M"),
                    "L2",
                    "L3"),
                "K3")
        ).Print();
    }

    private static Tree t(this string value, params Tree[] children) => new Tree(value, children);

    private static void Print(this Tree tree) => tree.Print(true, "");

    private static void Print(this Tree tree, bool last, string prefix) {
        (string current, string next) = last
            ? (prefix + "└─" + tree.Value, prefix + "  ")
            : (prefix + "├─" + tree.Value, prefix + "| ");
        Console.WriteLine(current[2..]);
        for (int c = 0; c < tree.Children.Length; c++) {
            tree.Children[c].Print(c == tree.Children.Length - 1, next);
        }
    }

    class Tree
    {
        public Tree(string value, params Tree[] children) => (Value, Children) = (value, children);
        public static implicit operator Tree(string value) => new Tree(value);
        public string Value { get; }
        public Tree[] Children { get; }
    }
    
}