Convert Binary Search Tree To Sorted Doubly Linked List

5 min read

A Binary Search Tree (BST) organizes data hierarchically, allowing for efficient search, insertion, and deletion operations with an average time complexity of O(log n). Even so, certain algorithms and system designs require linear, sequential access to sorted data. In practice, converting a BST into a sorted doubly linked list is a classic algorithmic problem that tests a developer's understanding of tree traversal, pointer manipulation, and recursion. This is where the doubly linked list shines, offering O(1) insertion and deletion at known positions and straightforward bidirectional traversal. This article provides a practical guide to mastering this conversion, covering the theoretical foundation, step-by-step implementation strategies, and complexity analysis.

Understanding the Core Concept

Before diving into code, it is crucial to visualize the structural relationship between the two data structures. In a BST, every node possesses a left pointer (to smaller values) and a right pointer (to larger values). In a sorted doubly linked list, every node possesses a prev pointer (to the previous/smaller element) and a next pointer (to the next/larger element).

The mapping is direct:

  • The BST left pointer becomes the List prev pointer. Because of that, * The BST right pointer becomes the List next pointer. Practically speaking, * The in-order traversal of a BST visits nodes in ascending order. Because of this, performing an in-order traversal while rewiring pointers effectively flattens the tree into the desired list.

The challenge lies in performing this rewiring in-place—without allocating new nodes—typically achieving O(N) time complexity and O(H) space complexity (where H is the height of the tree, due to the recursion stack).

Approach 1: Recursive In-Order Traversal (Standard Solution)

The most intuitive method leverages the natural ordering of recursive in-order traversal (Left -> Root -> Right). We maintain a reference to the previously visited node (prev) and the head of the resulting list (head).

Algorithm Steps

  1. Initialize two pointers: prev = null and head = null.
  2. Traverse the tree recursively using in-order logic.
  3. Process Current Node:
    • If prev is null, this is the leftmost (smallest) node. Mark it as head.
    • Otherwise, link prev.right = current and current.left = prev.
    • Update prev = current.
  4. Finalize: After traversal completes, head points to the start, and prev points to the end. For a circular list, connect head.left = prev and prev.right = head.

Python Implementation

class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def treeToDoublyList(root: 'Node') -> 'Node':
    if not root:
        return None

    # Use a list or nonlocal variable to hold references across recursive calls
    prev = [None]
    head = [None]

    def inorder(node):
        if not node:
            return
        
        # 1. Worth adding: traverse Left Subtree
        inorder(node. left)
        
        # 2. In practice, process Current Node
        # Link previous node to current
        if prev[0]:
            prev[0]. right = node
            node.And left = prev[0]
        else:
            # This is the smallest element (Head)
            head[0] = node
        
        # Update prev to current
        prev[0] = node
        
        # 3. Traverse Right Subtree
        inorder(node.

    inorder(root)
    
    # Optional: Make it Circular Doubly Linked List
    head[0].left = prev[0]
    prev[0].right = head[0]
    
    return head[0]

Java Implementation

class Node {
    public int val;
    public Node left;
    public Node right;
    public Node(int val) { this.val = val; }
}

class Solution {
    Node prev = null;
    Node head = null;

    public Node treeToDoublyList(Node root) {
        if (root == null) return null;
        helper(root);
        // Close the loop for circular list
        head.left = prev;
        prev.right = head;
        return head;
    }

    void helper(Node node) {
        if (node == null) return;
        
        helper(node.left);
        
        if (prev !So naturally, = null) {
            prev. In practice, right = node;
            node. left = prev;
        } else {
            head = node; // Leftmost node
        }
        prev = node;
        
        helper(node.

**Complexity Analysis:**
*   **Time:** *O(N)* — Every node is visited exactly once.
*   **Space:** *O(H)* — Recursion stack depth equals the height of the tree. *O(N)* worst case (skewed tree), *O(log N)* best case (balanced tree).

## Approach 2: Iterative In-Order Traversal (Explicit Stack)

Recursion carries the risk of **Stack Overflow** for extremely deep trees (e.g.Also, , a skewed tree with 100,000+ nodes). An iterative approach using an explicit stack mitigates this risk by utilizing heap memory instead of the limited call stack.

### Algorithm Steps

1.  Initialize `stack`, `curr = root`, `prev = null`, `head = null`.
2.  Loop while `curr != null` OR `stack` is not empty:
    *   Push all left children onto stack (`curr = curr.left`).
    *   Pop `node` from stack.
    *   Process `node` (link with `prev`, update `head`/`prev` exactly like recursive version).
    *   Move to right child (`curr = node.right`).
3.  Connect `head` and `prev` for circularity.

### Python Iterative Code

```python
def treeToDoublyListIterative(root):
    if not root: return None
    
    stack = []
    curr = root
    prev = None
    head = None
    
    while curr or stack:
        # Go as left as possible
        while curr:
            stack.append(curr)
            curr = curr.left
        
        # Process node
        node = stack.pop()
        
        if prev:
            prev.right = node
            node.left = prev
        else:
            head = node
        
        prev = node
        curr = node.right # Move to right subtree
    
    # Make circular
    head.left = prev
    prev.right = head
    return head

This approach maintains O(N) time and O(H) space but is significantly more solid for production environments handling large datasets And that's really what it comes down to..

Approach 3: Morris Traversal (O(1) Space)

For the ultimate space optimization, Morris Traversal allows in-order traversal without recursion or a stack by temporarily modifying the tree structure (creating "threads" to in-order successors) Most people skip this — try not to..

The Logic

  1. Initialize curr = root, prev = null, head = null.
  2. While curr exists:
    • Case A: No Left Child. Process curr. Move curr = curr.right.
    • Case B: Left Child Exists. Find curr's in-order predecessor (rightmost node in left subtree).
      • If predecessor's right is null: Create thread (predecessor.right = curr), move curr = curr.left.
      • If predecessor's right is curr: Thread exists (returning from left subtree). Remove thread (predecessor.right = null). Process curr. Move curr = curr.right.

Python Morris Implementation

def
Just Went Live

Freshest Posts

Similar Ground

Interesting Nearby

Thank you for reading about Convert Binary Search Tree To Sorted Doubly Linked List. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home