Trees
While you imagine forest, trees are a fundamental data structure in computer science, used to represent hierarchical data.
Trees are a type of graph but with a key distinction: they have no cycles, meaning there's only max one path between any two nodes.
Terminology
Node
A basic unit containing data and one or more pointers.
Edge
Connection between two nodes.
Root
The topmost node of the tree.
- Root has no parent.
- All other nodes are descendants of the root.
- There is always exactly one root node.
Subtree
The portion of the tree rooted at a particular node, consisting of that node together with all of its descendant nodes and the edges connecting them.
- Think of a subtree as a smaller tree growing from a branch of a larger tree.
- It has its own root (the branch) and its own structure (the leaves and branches below it).
Child
A node that is directly connected and one level below another node.
Nodes without children are called leaves.
Parent
A node that has one or more children.
Each node (except the root) has exactly one parent.
For instance, here:
- Node A (marked green) is root.
- Nodes B and C are children of node A.
- Node A is parent of B and C
- Nodes D and E are leaves.
- One of the most common tree type is binary tree, a tree where each node has at most 2 children.
- In binary trees we additionally can distinguish:
- Left Child: The node directly connected to the left of a parent node.
- Right Child: The node directly connected to the right of a parent node.
- For instance, in the example above, node D is left child of B and C is right child of A.
Practical Applications of Binary Trees
- Binary Search Trees (BSTs)
- Organize data for efficient searching, insertion, and deletion.
- Left child nodes contain values less than the parent.
- Right child nodes contain values greater than or equal to the parent.
- Expression Trees
- Represent mathematical expressions.
- Operators are stored in parent nodes.
- Operands are stored in leaf nodes.
- Trie
- A specialized tree for fast string searching.
- Decision Trees
- Used in machine learning for decision-making processes.
- Each node represents a decision or condition.
- Consider a binary search tree (BST) used to store integers.
- The root node contains the value 10.
- Its left child contains 5, and its right child contains 15.
- This structure allows efficient searching by comparing values at each node.
When searching in a BST, always start by comparing the target value with the root.
This helps you decide whether to explore the left or right subtree.
Binary Search Tree animation
Logical Operations on Trees
While insertion (adding new nodes) and deletion (removing nodes) operation in trees can be not specifically defined, some cases line BST has well defined process:
- Binary Search Tree (BST) Insertion:
- Start at the root.
- Compare the value to be inserted with the current node.
- Move left if the value is smaller, right if larger.
- Repeat until a null position is found, then insert the node.
- Binary Search Tree (BST) deletion:
- Deleting a leaf node:
- Simply remove the node.
- Deleting a node with one child:
- Remove the node and replace it with its child.
- Deleting a node with two children:
- Find the in-order successor (the smallest value in the right subtree) or in-order predecessor (the largest value in the left subtree).
- Replace the value of the node to be deleted with the successor (or predecessor).
- Delete the successor (or predecessor) node, which will fall into case 1 or 2.
- Deleting a leaf node:
While BST insertion is straightforward, deletion involves more steps and is more complex.
BST deletion animation
As often we work with smaller and smaller subtrees in a tree, recursion is natural solution for operations on trees.
Binary Tree Traversal Orders
Tree traversal
The process of visiting each node in a tree data structure in a specific order.
Tree traversals is essential for tasks like searching, sorting, and manipulating data stored in trees.
- Tree traversal is not limited to binary search trees.
- It applies to all types of trees, including binary trees, AVL trees, and more.
There are three primary types of tree traversal:
- In-order Traversal
- Pre-order Traversal
- Post-order Traversal
Each traversal method follows a unique pattern, which we'll explore in detail.
When analyzing tree traversal algorithms, always start by identifying the base case (e.g., an empty node) and the recursive steps (e.g., visiting left and right subtrees).
In-order Traversal
In-order traversal visits nodes in the following order:
- Traverse the left subtree.
- Visit the current node.
- Traverse the right subtree.
def inOrder(node):
if node is None:
return
inOrder(node.left) # Traverse left subtree
print(node.value)
inOrder(node.right) # Traverse right subtreeThis traversal is particularly useful for binary search trees, as it visits nodes in ascending order.
Pre-order Traversal
Pre-order traversal visits nodes in the following order:
- Visit the current node.
- Traverse the left subtree.
- Traverse the right subtree.
def preOrder(node):
if node is None:
return
print(node.value)
preOrder(node.left) # Traverse left subtree
preOrder(node.right) # Traverse right subtreePre-order traversal is useful for creating a copy of the tree or for problems where the root must be processed before its subtrees.
Post-order Traversal
Post-order traversal visits nodes in the following order:
- Traverse the left subtree.
- Traverse the right subtree.
- Visit the current node.
def postOrder(node):
if node is None:
return
postOrder(node.left) # Traverse left subtree
postOrder(node.right) # Traverse right subtree
print(node.value)Post-order traversal is often used when deleting nodes in a tree or evaluating expression trees, because it processes children before the parent.
- Can you identify the root, parent, and leaf nodes in a given binary tree?
- How does the concept of a subtree help in recursive algorithm design?
- Why is it important to distinguish between left and right children in a binary tree?
- Can you sketch a binary tree after inserting a series of values?
- How does removing a node with two children differ from removing a node with no children?
- Why is it important to maintain the properties of a binary search tree when modifying nodes?
- What is the primary difference between in-order and pre-order traversal?
- How does post-order traversal handle nodes with two children?
- Why is in-order traversal particularly useful for binary search trees?
How does the recursive nature of trees influence our understanding of hierarchical structures in both computing and the natural world?