Introduction to Trees in Java — A Brief Beginner’s Overview

Alexander Obregon
4 min readMar 15, 2023

--

Image Source

Introduction

Trees are a versatile and widely used data structure in computer science. They provide a natural way to represent hierarchical relationships and enable efficient searching, insertion, and deletion operations. In this blog post, we will explore the fundamentals of tree data structures in Java, learn about some common tree types, and see how to implement a basic binary tree.

Understanding Trees

A tree is a non-linear data structure consisting of nodes connected by edges. Each node contains a value and references to its child nodes. Trees have the following properties:

  • A single root node from which all other nodes descend
  • Each node has zero or more child nodes
  • There are no cycles in a tree

Some common tree terminology includes:

  • Root: The topmost node in the tree
  • Child: A node directly connected to another node (its parent)
  • Parent: A node that has one or more child nodes
  • Leaf: A node with no children
  • Sibling: Nodes with the same parent

Types of Trees

There are several types of trees, each with its unique properties and use cases. Some common tree types include:

  • Binary Trees: Each node has at most two children, often referred to as the left and right children
  • Binary Search Trees (BST): A binary tree where the left child is less than or equal to the parent node, and the right child is greater than the parent node
  • AVL Trees: A self-balancing binary search tree that maintains a balanced height
  • Red-Black Trees: A self-balancing binary search tree with specific color properties to maintain balance

Implementing a Basic Binary Tree in Java

To create a binary tree in Java, we’ll first define a Node class to represent the individual nodes in the tree:

class Node {
int value;
Node left;
Node right;

public Node(int value) {
this.value = value;
left = null;
right = null;
}
}

Now, we can create a BinaryTree class that will hold the root node and provide methods for inserting and traversing nodes:

class BinaryTree {
Node root;

public BinaryTree() {
root = null;
}

public void insert(int value) {
root = insertRecursive(root, value);
}

private Node insertRecursive(Node current, int value) {
if (current == null) {
return new Node(value);
}

if (value < current.value) {
current.left = insertRecursive(current.left, value);
} else if (value > current.value) {
current.right = insertRecursive(current.right, value);
} else {
// value already exists, do nothing
return current;
}

return current;
}
}

In this simple example, we’ve implemented a basic binary tree with an insert method that adds nodes in a sorted manner.

Searching in a Binary Tree

To search for a value in a binary tree, we’ll add a find method to our BinaryTree class:

public boolean find(int value) {
return findRecursive(root, value);
}

private boolean findRecursive(Node current, int value) {
if (current == null) {
return false;
}

if (value == current.value) {
return true;
}

return value < current.value
? findRecursive(current.left, value)
: findRecursive(current.right, value);
}

Deleting a Node in a Binary Tree

To delete a node with a given value from the binary tree, we’ll add a delete method to the BinaryTree class:

public void delete(int value) {
root = deleteRecursive(root, value);
}

private Node deleteRecursive(Node current, int value) {
if (current == null) {
return null;
}

if (value == current.value) {
// Node to be deleted found
// Case 1: Node with no children
if (current.left == null && current.right == null) {
return null;
}

// Case 2: Node with one child
if (current.left == null) {
return current.right;
}

if (current.right == null) {
return current.left;
}

// Case 3: Node with two children
int smallestValue = findSmallestValue(current.right);
current.value = smallestValue;
current.right = deleteRecursive(current.right, smallestValue);
return current;
}

if (value < current.value) {
current.left = deleteRecursive(current.left, value);
return current;
}

current.right = deleteRecursive(current.right, value);
return current;
}

private int findSmallestValue(Node root) {
return root.left == null ? root.value : findSmallestValue(root.left);
}

Traversing a Binary Tree

There are several ways to traverse a binary tree, including in-order, pre-order, and post-order traversal. Here, we’ll implement in-order traversal, which visits the left subtree, the current node, and then the right subtree:

public void traverseInOrder() {
traverseInOrderRecursive(root);
System.out.println();
}

private void traverseInOrderRecursive(Node current) {
if (current != null) {
traverseInOrderRecursive(current.left);
System.out.print(current.value + " ");
traverseInOrderRecursive(current.right);
}
}

Conclusion

Trees are an key data structure in computer science, with many practical applications in various domains. In this blog post, we’ve introduced the basic concepts of trees, explored some common tree types, and demonstrated how to implement a simple binary tree in Java with searching, deleting, and traversing functionalities. As you continue your journey with trees, you’ll encounter more advanced tree structures and algorithms that help solve complex problems efficiently.

  1. Tree Data Structures — GeeksforGeeks
  2. Binary Trees — TutorialsPoint

--

--

Alexander Obregon

Software Engineer, fervent coder & writer. Devoted to learning & assisting others. Connect on LinkedIn: https://www.linkedin.com/in/alexander-obregon-97849b229/