Explain Codes LogoExplain Codes Logo

How to print binary tree diagram in Java?

java
binary-tree
recursion
performance
Nikita BarsukovbyNikita Barsukov·Aug 16, 2024
TLDR

Here's a quick way to visualize a binary tree using recursion and pre-order traversal. The indentation helps to represent the tree depth.

class TreeNode { int val; TreeNode left, right; TreeNode(int val) { this.val = val; } } class BinaryTreePrinter { static void printTree(TreeNode root) { printSubtree(root, 0); } static void printSubtree(TreeNode node, int space) { if (node == null) return; space += 10; // This distance between levels shall keep tree in shape, summer body anyone? printSubtree(node.right, space); System.out.print("\n"); for (int i = 10; i < space; i++) System.out.print(" "); System.out.print(node.val + "\n"); printSubtree(node.left, space); } }

Use BinaryTreePrinter.printTree(root); to output the tree structure as a readable diagram.

Methodical walk-through for design of the printing algorithm

The "Fast Answer" segment covered on how to quickly print a binary tree. However, let's peel back the layers and delve into a design of enhanced tree printer inspired by the classic tree command in Linux. This advanced printer caters to a variety of trees, with smart spacing and elegant ASCII depiction.

Recursion and clever handling of white spaces

To portray a family-like hierarchy among nodes, we recursively deal with each node and its descendants. Maintaining the spacing based on their position in the tree is crucial. A core function, printNodeInternal is responsible for the whole printing logic, taking care of the indentation rules to provide an amazing user experience. It has extensive anti-whitespace measures to prevent needless spaces.

Crafting a PrintableNode interface

We will construct a PrintableNode interface, which will be implemented by our TreeNode. It standardizes the essential methods, such as getLeft(); getRight(), and getText(), thus promoting better compatibility and simplifying node operations.

Flexible output and the importance of performance optimization

Facilitating printing to any stream, we will use an OutputStreamWriter. To improve the readability and performance of the outcoming text, we apply StringBuilder in the toString() method.

Deep dive into advanced aspects of tree printing

For a perfectly printed tree, consider the following vital aspects:

Adapting to diverse node width

For trees with varying lengths of node values, widest node width calculation is essential to ensure consistent spacing at each level.

Level-wise node handling using ArrayList

For each tree level, we store references to its nodes in an ArrayList. This promotes level-wise traversal and helps to maintain the tree structure on output.

Separation of functionality: Insertion and Printing

Avoid mixing insertion logic with print functionality. Keeping separation permits focused design for a clean, understandable, and maintainable BTreePrinter.

Checking across different scenarios

To ensure robustness of your implementation, create test cases addressing various tree shapes. This ensures your tree printer can handle anything thrown at it, from towering oaks to lopsided bonsai.

Building the Swiss army knife of tree nodes

Creating a Node class capable of handling insertion and presentation. Given that node comparison can be required for some tree operations, our Node class implements the Comparable interface.

class Node implements Comparable<Node>, PrintableNode { int data; // Getter, setter methods are omitted for simplicity public Node getLeft() { /* Method to retrieve left child node */ } public Node getRight() { /* Method to retrieve right child node */ } public String getText() { /* Deliver node's data as a text representation */ } @Override public int compareTo(Node other) { /* Comparison logic helping the tree stay in shape */ } // Insertion and more here… }

FYI: This example uses integer data, but your love for generics can customize it for different data types.

More: For the tree-printing enthusiast

Explore following advanced tree-printing techniques:

Player of all types: Nodes handle different data types

By adding generics to your Node class, your binary tree can be adapted to varying data types ensuring your printer is type-agnostic.

Get drawn in: Interactive tree visualization

Plunge into JavaFX for interactive visualizations. This enables real-time tree diagram updates upon operations like node additions and deletions.

Express your tree: ASCII art and unicode characters

Elevate your tree diagram's look and feel with custom ASCII art or unicode characters to get an expressive binary tree representation.