Bird
Raised Fist0
DSA Javascriptprogramming~10 mins

Morris Traversal Inorder Without Stack in DSA Javascript - Execution Trace

Choose your learning style10 modes available
Concept Flow - Morris Traversal Inorder Without Stack
Start at root
↓
Check if current.left is null?
Yes→Visit current node, move to current.right
No↓
Find predecessor in left subtree
↓
Check if predecessor.right is null?
Yes→Make thread: predecessor.right = current, move current to current.left
No↓
Remove thread: predecessor.right = null, visit current, move current to current.right
↓
Repeat until current is null
↓
Traversal complete
The traversal moves through the tree without stack by creating temporary threads to predecessors, visiting nodes in inorder sequence.
Execution Sample
DSA Javascript
function morrisInorder(root) {
  let current = root;
  while (current !== null) {
    if (current.left === null) {
      console.log(current.val);
      current = current.right;
    } else {
      let predecessor = current.left;
      while (predecessor.right !== null && predecessor.right !== current) {
        predecessor = predecessor.right;
      }
      if (predecessor.right === null) {
        predecessor.right = current;
        current = current.left;
      } else {
        predecessor.right = null;
        console.log(current.val);
        current = current.right;
      }
    }
  }
}
This code prints the inorder traversal of a binary tree using Morris Traversal without using stack or recursion.
Execution Table
StepOperationCurrent NodePredecessorThread Created/RemovedVisited NodeVisual Tree State
1Start at root1N/ANoNo1 / \ 2 3
2current.left != null, find predecessor12NoNo1 / \ 2 3
3predecessor.right == null, create thread12Thread created: 2.right = 1No1 / \ 2→ 3
4Move current to left child2N/ANoNo1 / \ 2→ 3
5current.left == null, visit node2N/ANoVisited 21 / \ 2→ 3
6Move current to right child1N/ANoNo1 / \ 2→ 3
7current.left != null, find predecessor12NoNo1 / \ 2→ 3
8predecessor.right == current, remove thread12Thread removed: 2.right = nullNo1 / \ 2 3
9Visit current node1N/ANoVisited 11 / \ 2 3
10Move current to right child3N/ANoNo1 / \ 2 3
11current.left == null, visit node3N/ANoVisited 31 / \ 2 3
12Move current to right childnullN/ANoNo1 / \ 2 3
13current is null, traversal endsnullN/ANoNo1 / \ 2 3
💡 Traversal ends when current becomes null after visiting all nodes.
Variable Tracker
VariableStartAfter Step 3After Step 5After Step 8After Step 9After Step 11Final
current112113null
predecessorN/A2N/A2N/AN/AN/A
threadNoYes (2.right=1)Yes (2.right=1)No (2.right=null)NoNoNo
Key Moments - 3 Insights
Why do we create a thread from predecessor.right to current?
Creating the thread (see Step 3) allows us to return to the current node after finishing the left subtree without using a stack.
Why do we remove the thread later?
Removing the thread (see Step 8) restores the original tree structure after visiting the current node.
Why do we visit nodes only when current.left is null or after removing a thread?
Visiting nodes at these points (Steps 5, 9, 11) ensures inorder sequence: left subtree, node, then right subtree.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step is the thread from node 2 to node 1 created?
AStep 5
BStep 8
CStep 3
DStep 10
💡 Hint
Check the 'Thread Created/Removed' column in the execution table.
At which step does the traversal visit node 1?
AStep 5
BStep 9
CStep 8
DStep 11
💡 Hint
Look at the 'Visited Node' column in the execution table.
If the tree had no left children, how would the traversal proceed?
AIt would visit nodes immediately and move to right child.
BIt would create threads for every node.
CIt would get stuck in an infinite loop.
DIt would skip visiting nodes.
💡 Hint
Refer to the condition when current.left is null in the code and execution table.
Concept Snapshot
Morris Traversal Inorder Without Stack:
- Uses threaded binary tree concept.
- Creates temporary right links (threads) to predecessors.
- Visits nodes when left subtree is done.
- Removes threads to restore tree.
- Traverses in O(n) time and O(1) space.
Full Transcript
Morris Traversal is a way to do inorder traversal of a binary tree without using extra space like stack or recursion. It works by creating temporary threads from a node's inorder predecessor back to the node. This allows the traversal to return to the node after finishing its left subtree. When the thread is encountered again, it is removed and the node is visited. If a node has no left child, it is visited immediately and traversal moves to the right child. This process continues until all nodes are visited and the tree is restored to its original shape. The execution table shows each step including thread creation, removal, and node visits. The variable tracker shows how current and predecessor pointers move and how threads are created and removed. Key moments clarify why threads are needed and when nodes are visited. The visual quiz tests understanding of these steps. This method achieves inorder traversal in linear time with constant space.

Practice

(1/5)
1. What is the main advantage of Morris Traversal for inorder tree traversal compared to traditional methods?
easy
A. It only works on binary search trees
B. It is faster than all other traversal methods
C. It requires a queue to store nodes
D. It uses no extra space like stack or recursion

Solution

  1. Step 1: Understand Morris Traversal space usage

    Morris Traversal modifies tree links temporarily to avoid using stack or recursion, so it uses O(1) extra space.
  2. Step 2: Compare with traditional methods

    Traditional inorder traversal uses stack or recursion which requires O(h) space, where h is tree height.
  3. Final Answer:

    It uses no extra space like stack or recursion -> Option D
  4. Quick Check:

    Morris Traversal = O(1) space [OK]
Hint: Morris Traversal avoids stack and recursion for space savings [OK]
Common Mistakes:
  • Thinking Morris Traversal is faster in time complexity
  • Assuming it only works on binary search trees
  • Believing it uses extra data structures like queues
2. Which of the following is the correct way to find the inorder predecessor of a node curr in Morris Traversal?
easy
A. Move to the left child of curr and then keep moving right until right child is null or curr
B. Move to the right child of curr until null
C. Move to the left child of curr only once
D. Move to the right child of curr and then keep moving left until left child is null

Solution

  1. Step 1: Identify inorder predecessor in Morris Traversal

    The inorder predecessor is the rightmost node in the left subtree of curr.
  2. Step 2: Traverse left subtree then rightmost path

    Start at curr.left, move right repeatedly until right child is null or points back to curr.
  3. Final Answer:

    Move to the left child of curr and then keep moving right until right child is null or curr -> Option A
  4. Quick Check:

    Inorder predecessor = left subtree's rightmost node [OK]
Hint: Inorder predecessor = left child then rightmost path [OK]
Common Mistakes:
  • Moving right child first instead of left
  • Stopping after one left move without going right
  • Confusing predecessor with successor
3. What will be the output of Morris inorder traversal on the following binary tree?
    2
   / \
  1   3
Assuming the traversal prints node values in order.
medium
A. [1, 3, 2]
B. [2, 1, 3]
C. [1, 2, 3]
D. [3, 2, 1]

Solution

  1. Step 1: Understand inorder traversal order

    Inorder traversal visits left subtree, then current node, then right subtree.
  2. Step 2: Apply Morris traversal on given tree

    Left child is 1, root is 2, right child is 3, so output is [1, 2, 3].
  3. Final Answer:

    [1, 2, 3] -> Option C
  4. Quick Check:

    Inorder = left, root, right = [1, 2, 3] [OK]
Hint: Inorder prints left, root, right nodes [OK]
Common Mistakes:
  • Confusing preorder or postorder with inorder
  • Mixing node visit order
  • Assuming traversal prints in reverse
4. Consider this snippet of Morris Traversal code:
while (curr !== null) {
  if (curr.left === null) {
    console.log(curr.val);
    curr = curr.right;
  } else {
    let pred = curr.left;
    while (pred.right !== null && pred.right !== curr) {
      pred = pred.right;
    }
    if (pred.right === null) {
      pred.right = curr;
      curr = curr.left;
    } else {
      pred.right = null;
      console.log(curr.val);
      curr = curr.right;
    }
  }
}
What is the error in this code?
medium
A. It misses printing the current node after restoring links
B. It never prints the current node's value
C. It creates infinite loop by not updating curr
D. It incorrectly sets pred.right to curr.left

Solution

  1. Step 1: Check when node values are printed

    Values are printed only when curr.left === null, but after restoring links, printing is missing.
  2. Step 2: Identify missing print after restoring links

    After setting pred.right = null, the code moves curr = curr.right without printing curr.val.
  3. Final Answer:

    It misses printing the current node after restoring links -> Option A
  4. Quick Check:

    Print missing after restoring links = bug [OK]
Hint: Print node after restoring links to avoid missing values [OK]
Common Mistakes:
  • Not printing node after restoring predecessor link
  • Confusing when to update curr pointer
  • Incorrectly modifying tree structure
5. You want to modify Morris Traversal inorder to collect node values in an array instead of printing. Which change is necessary to correctly collect all nodes in order?
hard
A. Push curr.val only when curr.left === null
B. Push curr.val both when curr.left === null and after restoring links
C. Push curr.val only after restoring links
D. Push curr.val before moving to left child

Solution

  1. Step 1: Identify when nodes are visited in Morris Traversal

    Nodes are visited either when curr.left === null or after restoring the threaded link.
  2. Step 2: Collect values at both visit points

    To collect all nodes in inorder, push curr.val both when curr.left === null and after restoring links (before moving right).
  3. Final Answer:

    Push curr.val both when curr.left === null and after restoring links -> Option B
  4. Quick Check:

    Collect values at both visits = correct inorder [OK]
Hint: Collect node values at both visits for full inorder [OK]
Common Mistakes:
  • Collecting values only once misses nodes
  • Collecting before moving left causes wrong order
  • Ignoring second visit after restoring links
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard