A **Binary Tree** is a finite set of elements that is either empty or is partitioned into three disjoint subsets. The first subset contains a single element called root. The other two subsets are themselves binary trees and called as **left** and **right** subtrees of original tree. Each element of a binary tree is called a node of the tree.

Consider this Binary tree

Here, `10`

is the `root node`

, `node 2`

is the `left child`

of the `root node`

and `node 21`

is the `right child`

of the `root node`

and similarly for the rest of the tree.

Visualizing a binary tree can help in understanding its structure and the relationships between its nodes. Let’s write a Python script to pretty print a binary tree in Python using ASCII characters to represent the tree structure.

###### Printing the Binary Tree

To print the binary tree, we need a recursive function that will traverse the tree and print each node in a structured manner. We’ll use ASCII characters to draw the tree branches:

`│`

to represent a vertical branch`└──`

to represent a left child`┌──`

to represent a right child

###### Pseudocode

The idea here is to do a Depth First Traversal of the Binary tree and determine each node’s position in the tree.

Depth-First Traversal

1. First recursively traverse the right subtree,

2. Then process the current node,

3. And finally traverse the left subtree.

Processing the node

1. Use a prefix parameter to keeps track of the current indentation level and structure.

2. Use is_left parameter to track whether the current node is a left child or right child.

3. The current node’s value is printed with the appropriate prefix. If it’s a left child, the prefix includes └──; if it’s a right child, the prefix includes ┌──.

This ensures that the tree is printed from top to bottom and right to left.

Depth First Traversal is discussed in detail in this post – DFS (Depth-First Search) in Binary Trees and Graphs

###### Code Implementation

```
# Class to represent a Tree node
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def print_tree(root, prefix="", is_left=True):
if root is not None:
print_tree(root.right, prefix + ("│ " if is_left else " "), False)
print(prefix + ("└── " if is_left else "┌── ") + str(root.value))
print_tree(root.left, prefix + (" " if is_left else "│ "), True)
# Example Usage
root = TreeNode(10)
root.left = TreeNode(2)
root.right = TreeNode(21)
root.right.left = TreeNode(15)
root.right.right = TreeNode(31)
print_tree(root)
```

**Output**

│ ┌── 31

│ ┌── 21

│ │ └── 15

└── 10

└── 2

**Time complexity: O(N),** `print_tree`

function visits each node exactly once, performing constant-time operations for each node.**Auxiliary Space:** **O(N),** primary space usage comes from the recursive call stack, which can grow to a depth of N in the worst case (skewed tree).

The `print_tree`

function is efficient in terms of both time and space complexity for most practical purposes. This method is particularly useful for debugging and understanding the structure of Binary Trees.