Preorder vs Inorder vs Postorder
Last Updated :
17 Apr, 2024
In Preorder Traversal, the root node is visited first, followed by the left and right subtrees. Inorder Traversal starts with the left subtree, visits the root, and then the right subtree, often used in binary search trees. Postorder Traversal begins with the left subtree, moves to the right subtree, and visits the root last, useful for deleting nodes. In this article, we will discuss the Tree Traversal Techniques used in data structure and algorithms with their differences.
Preorder traversal is defined as a type of tree traversal that follows the Root-Left-Right policy where:
- The root node of the subtree is visited first.
- Then the left subtree is traversed.
- At last, the right subtree is traversed.
Inorder traversal is defined as a type of tree traversal technique that follows the Left-Root-Right pattern, such that:
- The left subtree is traversed first.
- Then the root node for that subtree is traversed.
- Finally, the right subtree is traversed.
Postorder traversal is defined as a type of tree traversal that follows the Left-Right-Root policy such that for each node:
- The left subtree is traversed first.
- Then the right subtree is traversed.
- Finally, the root node of the subtree is traversed.
Below is the Implementation of the above idea:
C++
#include <iostream>
using namespace std;
// Definition of a binary tree node
class TreeNode {
public:
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) : val(val), left(nullptr), right(nullptr) {}
};
// Pre-order traversal
void preorderTraversal(TreeNode* root) {
if (root) {
cout << root->val << " "; // Visit root
preorderTraversal(root->left); // Recursively traverse left subtree
preorderTraversal(root->right); // Recursively traverse right subtree
}
}
// In-order traversal
void inorderTraversal(TreeNode* root) {
if (root) {
inorderTraversal(root->left); // Recursively traverse left subtree
cout << root->val << " "; // Visit root
inorderTraversal(root->right); // Recursively traverse right subtree
}
}
// Post-order traversal
void postorderTraversal(TreeNode* root) {
if (root) {
postorderTraversal(root->left); // Recursively traverse left subtree
postorderTraversal(root->right); // Recursively traverse right subtree
cout << root->val << " "; // Visit root
}
}
// Example tree
int main() {
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
root->right->right = new TreeNode(6);
// Pre-order traversal
cout << "Pre-order traversal: ";
preorderTraversal(root);
cout << endl;
// In-order traversal
cout << "In-order traversal: ";
inorderTraversal(root);
cout << endl;
// Post-order traversal
cout << "Post-order traversal: ";
postorderTraversal(root);
cout << endl;
return 0;
}
Java
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public class Main {
// Pre-order traversal
public static void preorderTraversal(TreeNode root) {
if (root != null) {
System.out.print(root.val + " "); // Visit root
preorderTraversal(root.left); // Recursively traverse left subtree
preorderTraversal(root.right); // Recursively traverse right subtree
}
}
// In-order traversal
public static void inorderTraversal(TreeNode root) {
if (root != null) {
inorderTraversal(root.left); // Recursively traverse left subtree
System.out.print(root.val + " "); // Visit root
inorderTraversal(root.right); // Recursively traverse right subtree
}
}
// Post-order traversal
public static void postorderTraversal(TreeNode root) {
if (root != null) {
postorderTraversal(root.left); // Recursively traverse left subtree
postorderTraversal(root.right); // Recursively traverse right subtree
System.out.print(root.val + " "); // Visit root
}
}
// Example tree
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.right = new TreeNode(6);
// Pre-order traversal
System.out.print("Pre-order traversal: ");
preorderTraversal(root);
System.out.println();
// In-order traversal
System.out.print("In-order traversal: ");
inorderTraversal(root);
System.out.println();
// Post-order traversal
System.out.print("Post-order traversal: ");
postorderTraversal(root);
System.out.println();
}
}
Python3
# Definition of a binary tree node
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
# Pre-order traversal
def preorder_traversal(root):
if root:
print(root.val, end=" ") # Visit root
preorder_traversal(root.left) # Recursively traverse left subtree
preorder_traversal(root.right) # Recursively traverse right subtree
# In-order traversal
def inorder_traversal(root):
if root:
inorder_traversal(root.left) # Recursively traverse left subtree
print(root.val, end=" ") # Visit root
inorder_traversal(root.right) # Recursively traverse right subtree
# Post-order traversal
def postorder_traversal(root):
if root:
postorder_traversal(root.left) # Recursively traverse left subtree
postorder_traversal(root.right) # Recursively traverse right subtree
print(root.val, end=" ") # Visit root
# Example tree
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.right.right = TreeNode(6)
# Pre-order traversal
print("Pre-order traversal:")
preorder_traversal(root)
print()
# In-order traversal
print("In-order traversal:")
inorder_traversal(root)
print()
# Post-order traversal
print("Post-order traversal:")
postorder_traversal(root)
print()
C#
using System;
// Definition of a binary tree node
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public class BinaryTreeTraversal {
// Pre-order traversal
public static void PreorderTraversal(TreeNode root) {
if (root != null) {
Console.Write(root.val + " "); // Visit root
PreorderTraversal(root.left); // Recursively traverse left subtree
PreorderTraversal(root.right); // Recursively traverse right subtree
}
}
// In-order traversal
public static void InorderTraversal(TreeNode root) {
if (root != null) {
InorderTraversal(root.left); // Recursively traverse left subtree
Console.Write(root.val + " "); // Visit root
InorderTraversal(root.right); // Recursively traverse right subtree
}
}
// Post-order traversal
public static void PostorderTraversal(TreeNode root) {
if (root != null) {
PostorderTraversal(root.left); // Recursively traverse left subtree
PostorderTraversal(root.right); // Recursively traverse right subtree
Console.Write(root.val + " "); // Visit root
}
}
// Example tree
public static void Main(string[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.right = new TreeNode(6);
// Pre-order traversal
Console.Write("Pre-order traversal: ");
PreorderTraversal(root);
Console.WriteLine();
// In-order traversal
Console.Write("In-order traversal: ");
InorderTraversal(root);
Console.WriteLine();
// Post-order traversal
Console.Write("Post-order traversal: ");
PostorderTraversal(root);
Console.WriteLine();
}
}
JavaScript
// Definition of a binary tree node
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
// Pre-order traversal
function preorderTraversal(root) {
if (root) {
console.log(root.val); // Visit root
preorderTraversal(root.left); // Recursively traverse left subtree
preorderTraversal(root.right); // Recursively traverse right subtree
}
}
// In-order traversal
function inorderTraversal(root) {
if (root) {
inorderTraversal(root.left); // Recursively traverse left subtree
console.log(root.val); // Visit root
inorderTraversal(root.right); // Recursively traverse right subtree
}
}
// Post-order traversal
function postorderTraversal(root) {
if (root) {
postorderTraversal(root.left); // Recursively traverse left subtree
postorderTraversal(root.right); // Recursively traverse right subtree
console.log(root.val); // Visit root
}
}
// Example tree
let root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.right = new TreeNode(6);
// Pre-order traversal
console.log("Pre-order traversal:");
preorderTraversal(root);
// In-order traversal
console.log("In-order traversal:");
inorderTraversal(root);
// Post-order traversal
console.log("Post-order traversal:");
postorderTraversal(root);
OutputPre-order traversal: 1 2 4 5 3 6
In-order traversal: 4 2 5 1 3 6
Post-order traversal: 4 5 2 6 3 1
Preorder vs Inorder vs Postorder:
Attribute
| Pre-order
| In-order
| Post-order
|
---|
Visit Order
| Root, Left Subtree, Right Subtree
| Left Subtree, Root, Right Subtree
| Left Subtree, Right Subtree, Root
|
---|
Sorted Order (BST)
| No
| Yes
| Yes
|
---|
Expression Tree
| Prefix (Polish) Notation
| Infix (Standard) Notation
| Postfix (Reverse Polish) Notation
|
---|
Evaluation Order
| Operators come before operands
| Operators come between operands
| Operators come after operands
|
---|
Memory Usage
| No additional memory for tracking traversal, stack space for recursion/iteration
| No additional memory for tracking traversal, stack space for recursion/iteration
| No additional memory for tracking traversal, stack space for recursion/iteration
|
---|
Left-Right Symmetry
| Not symmetric
| Symmetric
| Not symmetric
|
---|
Application
| Constructing expression trees, cloning/copying trees, prefix notation
| In-order traversal of BST for sorted order, expression evaluation
| Deleting nodes in binary trees, post-fix notation, expression evaluation
|
---|
Performance
| Better for copying/cloning trees, prefix notation
| Suitable for sorting BST elements, expression evaluation
| Suitable for deleting nodes, post-fix notation, expression evaluation
|
---|
Tree Modification
| Easy to copy/cloning, preserving original structure
| Not ideal for modification
| Difficult for modification, requires reversing
|
---|
Similar Reads
DSA Tutorial - Learn Data Structures and Algorithms DSA (Data Structures and Algorithms) is the study of organizing data efficiently using data structures like arrays, stacks, and trees, paired with step-by-step procedures (or algorithms) to solve problems effectively. Data structures manage how data is stored and accessed, while algorithms focus on
7 min read
Quick Sort QuickSort is a sorting algorithm based on the Divide and Conquer that picks an element as a pivot and partitions the given array around the picked pivot by placing the pivot in its correct position in the sorted array. It works on the principle of divide and conquer, breaking down the problem into s
12 min read
Merge Sort - Data Structure and Algorithms Tutorials Merge sort is a popular sorting algorithm known for its efficiency and stability. It follows the divide-and-conquer approach. It works by recursively dividing the input array into two halves, recursively sorting the two halves and finally merging them back together to obtain the sorted array. Merge
14 min read
Data Structures Tutorial Data structures are the fundamental building blocks of computer programming. They define how data is organized, stored, and manipulated within a program. Understanding data structures is very important for developing efficient and effective algorithms. What is Data Structure?A data structure is a st
2 min read
Bubble Sort Algorithm Bubble Sort is the simplest sorting algorithm that works by repeatedly swapping the adjacent elements if they are in the wrong order. This algorithm is not suitable for large data sets as its average and worst-case time complexity are quite high.We sort the array using multiple passes. After the fir
8 min read
Breadth First Search or BFS for a Graph Given a undirected graph represented by an adjacency list adj, where each adj[i] represents the list of vertices connected to vertex i. Perform a Breadth First Search (BFS) traversal starting from vertex 0, visiting vertices from left to right according to the adjacency list, and return a list conta
15+ min read
Binary Search Algorithm - Iterative and Recursive Implementation Binary Search Algorithm is a searching algorithm used in a sorted array by repeatedly dividing the search interval in half. The idea of binary search is to use the information that the array is sorted and reduce the time complexity to O(log N). Binary Search AlgorithmConditions to apply Binary Searc
15 min read
Insertion Sort Algorithm Insertion sort is a simple sorting algorithm that works by iteratively inserting each element of an unsorted list into its correct position in a sorted portion of the list. It is like sorting playing cards in your hands. You split the cards into two groups: the sorted cards and the unsorted cards. T
9 min read
Array Data Structure Guide In this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
4 min read
Sorting Algorithms A Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read