Serialize and Deserialize a Binary Tree (original) (raw)

Last Updated : 4 Oct, 2025

Given the **root of abinary tree, Complete the functions:

**Note: Multiple nodes can have the same data and the node values are always positive.

Table of Content

[Approach 1] Using Preorder Traversal (Recursive) - O(n) Time and O(n) Space

The idea is to use preorder traversal for serialization. While traversing, if a node is not null, store its value else store -1 as a marker.

Try It Yourselfredirect icon

**Pseudo-code Idea (Deserialization)

#include #include #include using namespace std;

// Node Structure class Node { public: int data; Node* left, *right; Node (int x) { data = x; left = nullptr; right = nullptr; } };

// Function to store the preorder void serializePreOrder(Node* root, vector &arr) {

// Push -1 if root is null.
if (root == nullptr) {
    arr.push_back(-1);
    return;
}

// Push the root into result.
arr.push_back(root->data);
serializePreOrder(root->left, arr);
serializePreOrder(root->right, arr);

}

// Main function to serialize a tree. vector serialize(Node *root) { vector arr; serializePreOrder(root, arr); return arr; }

// Function to restore the array from preorder Node* deserializePreOrder(int &i, vector &arr) {

// if element is -1 return null
if (arr[i] == -1){
    i++;
    return nullptr;
}

// Create the root node.
Node* root = new Node(arr[i]);
i++;

// Create the left and right subtree.
root->left = deserializePreOrder(i, arr);
root->right = deserializePreOrder(i, arr);

return root;

}

Node * deSerialize(vector &arr) { int i = 0; return deserializePreOrder(i, arr); }

int main() {

//       10
//     /    \
//    20    30
//  /   \
// 40  60
Node* root = new Node(10);        
root->left = new Node(20);        
root->right = new Node(30);       
root->left->left = new Node(40);
root->left->right = new Node(60); 

vector<int> arr = serialize(root);
Node* res = deSerialize(arr);

}

Java

import java.util.ArrayList; import java.util.Queue; import java.util.LinkedList;

// Node Structure class Node { int data; Node left, right; Node (int x) { data = x; left = null; right = null; } }

class GFG {

// Function to store the preorder
static void serializePreOrder(Node root, ArrayList<Integer> arr) {
    
    // Push -1 if root is null.
    if (root == null) {
        arr.add(-1);
        return;
    }
    
    // Push the root into result.
    arr.add(root.data);
    serializePreOrder(root.left, arr);
    serializePreOrder(root.right, arr);
}

//  function to serialize a tree.
static ArrayList<Integer> serialize(Node root) {
    ArrayList<Integer> arr = new ArrayList<>();
    serializePreOrder(root, arr);
    return arr;
}

// Function to restore the tree from preorder
static Node deserializePreOrder(int[] i, ArrayList<Integer> arr) {
    
    // if elemnt is -1 return null
    if (arr.get(i[0]) == -1) {
        i[0]++;
        return null;
    }
    
    // Create the root node.
    Node root = new Node(arr.get(i[0]));
    i[0]++;
    
    // Create the left and right subtree.
    root.left = deserializePreOrder(i, arr);
    root.right = deserializePreOrder(i, arr);
    
    return root;
}

// function to deserialize a tree.
static Node deSerialize(ArrayList<Integer> arr) {
   int[] i = {0};
   return deserializePreOrder(i, arr);
}

public static void main(String[] args) {

    //       10
    //     /    \
    //    20    30
    //  /   \
    // 40  60
    Node root = new Node(10);        
    root.left = new Node(20);        
    root.right = new Node(30);       
    root.left.left = new Node(40);
    root.left.right = new Node(60); 
    
    ArrayList<Integer> arr = serialize(root);
    Node res = deSerialize(arr);
}

}

Python

from collections import deque

Node Structure

class Node: def init(self, x): self.data = x self.left = None self.right = None

Function to store preorder

def serializePreOrder(root, arr):

# Push -1 if root is null.
if root is None:
    arr.append(-1)
    return

# Push the root into result.
arr.append(root.data)
serializePreOrder(root.left, arr)
serializePreOrder(root.right, arr)

function to serialize a tree.

def serialize(root): arr = [] serializePreOrder(root, arr) return arr

Function to restore the tree from preorder

def deserializePreOrder(i, arr):

# if element is -1 return null
if arr[i[0]] == -1:
    i[0] += 1
    return None

# Create the root node.
root = Node(arr[i[0]])
i[0] += 1

# Create the left and right subtree.
root.left = deserializePreOrder(i, arr)
root.right = deserializePreOrder(i, arr)

return root

function to deserialize a tree.

def deSerialize(arr): i = [0] return deserializePreOrder(i, arr)

if name == "main":

#       10
#     /    \
#    20    30
#  /   \
# 40  60
root = Node(10)        
root.left = Node(20)        
root.right = Node(30)       
root.left.left = Node(40)
root.left.right = Node(60) 

arr = serialize(root)
res = deSerialize(arr)

C#

using System; using System.Collections.Generic;

// Node Structure class Node { public int data; public Node left, right; public Node(int x) { data = x; left = null; right = null; } }

class GFG {

// Function to store the preorder
static void serializePreOrder(Node root, List<int> arr) {

    // Push -1 if root is null.
    if (root == null) {
        arr.Add(-1);
        return;
    }

    // Push the root into result.
    arr.Add(root.data);
    serializePreOrder(root.left, arr);
    serializePreOrder(root.right, arr);
}

//  function to serialize a tree.
static List<int> serialize(Node root)
{
    List<int> arr = new List<int>();
    serializePreOrder(root, arr);
    return arr;
}

// Function to restore the tree from preorder
static Node deserializePreOrder(ref int i,
                                List<int> arr) {

    // if element is -1 return null
    if (arr[i] == -1) {
        i++;
        return null;
    }

    // Create the root node.
    Node root = new Node(arr[i]);
    i++;

    // Create the left and right subtree.
    root.left = deserializePreOrder(ref i, arr);
    root.right = deserializePreOrder(ref i, arr);

    return root;
}

//  function to deserialize a tree.
static Node deSerialize(List<int> arr) {
    int i = 0;
    return deserializePreOrder(ref i, arr);
}

static void Main() {

    //       10
    //     /    \
    //    20    30
    //  /   \
    // 40  60
    Node root = new Node(10);
    root.left = new Node(20);
    root.right = new Node(30);
    root.left.left = new Node(40);
    root.left.right = new Node(60);

    List<int> arr = serialize(root);

    // Variable assigned but never used
    #pragma warning disable CS0219
    Node res = deSerialize(arr);
    #pragma warning restore CS0219
}

}

JavaScript

// Node Structure class Node { constructor(x) { this.data = x; this.left = null; this.right = null; } }

// Function to store the preorder function serializePreOrder(root, arr) {

// Push -1 if root is null.
if (root === null) {
    arr.push(-1);
    return;
}

// Push the root into result.
arr.push(root.data);
serializePreOrder(root.left, arr);
serializePreOrder(root.right, arr);

}

// function to serialize a tree. function serialize(root) { const arr = []; serializePreOrder(root, arr); return arr; }

// Function to restore the tree from preorder function deserializePreOrder(i, arr) {

// if element is -1 return null
if (arr[i[0]] === -1) {
    i[0]++;
    return null;
}

// Create the root node.
const root = new Node(arr[i[0]]);
i[0]++;

// Create the left and right subtree.
root.left = deserializePreOrder(i, arr);
root.right = deserializePreOrder(i, arr);

return root;

}

// function to deserialize a tree. function deserialize(arr) { const i = [0]; return deserializePreOrder(i, arr); }

// Driver Code

// 10 // /
// 20 30 // /
// 40 60 const root = new Node(10); root.left = new Node(20); root.right = new Node(30); root.left.left = new Node(40); root.left.right = new Node(60);

const arr = serialize(root); const res = deserialize(arr);

`

[Approach 2] Using Level Order Traversal - O(n) Time and O(n) Space

The idea is to use level-order traversal for serialization. Push the root into a queue and traverse the tree level by level. For each node, if it exists, store its value and push its left and right children into the queue; if it’s null, store -1 to mark null.
For deserialization, create the root from the first element and push it into a queue. Then, for each element in the array, pop a node from the queue and link its left and right children if the element is -1, the child is null; otherwise, create the node and push it into the queue. This ensures the tree structure is fully preserved.

C++ `

#include #include #include using namespace std;

// Node Structure class Node { public: int data; Node* left, *right; Node (int x) { data = x; left = nullptr; right = nullptr; } };

// function to serialize a tree. vector serialize(Node *root) { vector arr;

queue<Node*> q;
q.push(root);

while (!q.empty()) {
    Node* curr = q.front();
    q.pop();
    
    // If curr node is null,
    // append -1 to result.
    if (curr == nullptr) {
        arr.push_back(-1);
        continue;
    }
    
    // else push its value into
    // result and push left and right
    // child nodes into queue.
    arr.push_back(curr->data);
    
    q.push(curr->left);
    q.push(curr->right);
}

return arr;

}

// function to deserialize a tree. Node * deSerialize(vector &arr) {

if (arr[0]==-1) return nullptr;

// create root node and push // it into queue Node* root = new Node(arr[0]); queue<Node*> q; q.push(root);

int i = 1; while (!q.empty()) { Node* curr = q.front(); q.pop();

   // If left node is not null
   if (arr[i]!=-1) {
       Node* left = new Node(arr[i]);
       curr->left = left;
       q.push(left);
   }
   i++;
   
   // If right node is not null
   if (arr[i]!=-1) {
       Node* right = new Node(arr[i]);
       curr->right = right;
       q.push(right);
   }
   i++;

}

return root; }

int main() {

// Create a hard coded tree
//       10
//     /    \
//    20    30
//  /   \
// 40  60
Node* root = new Node(10);        
root->left = new Node(20);        
root->right = new Node(30);       
root->left->left = new Node(40);
root->left->right = new Node(60); 

vector<int> arr = serialize(root);
Node* res = deSerialize(arr);

}

Java

import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue;

// Node Structure class Node { int data; Node left, right; Node(int x) { data = x; left = null; right = null; } }

class GFG {

// Main function to serialize a tree.
static ArrayList<Integer> serialize(Node root) {
    ArrayList<Integer> arr = new ArrayList<>();
    Queue<Node> q = new LinkedList<>();
    q.add(root);

    while (!q.isEmpty()) {
        Node curr = q.poll();

        // If curr node is null,
        // append -1 to result.
        if (curr == null) {
            arr.add(-1);
            continue;
        }

        // else push its value into
        // result and push left and right
        // child nodes into queue.
        arr.add(curr.data);
        q.add(curr.left);
        q.add(curr.right);
    }

    return arr;
}

// Main function to deserialize a tree.
static Node deSerialize(ArrayList<Integer> arr) {

    // base case
    if (arr.get(0) == -1) return null;

    // create root node and push 
    // it into queue
    Node root = new Node(arr.get(0));
    Queue<Node> q = new LinkedList<>();
    q.add(root);

    int i = 1;
    while (!q.isEmpty()) {
        Node curr = q.poll();

        // If left node is not null
        if (arr.get(i) != -1) {
            Node left = new Node(arr.get(i));
            curr.left = left;
            q.add(left);
        }
        i++;

        // If right node is not null
        if (arr.get(i) != -1) {
            Node right = new Node(arr.get(i));
            curr.right = right;
            q.add(right);
        }
        i++;
    }

    return root;
}


public static void main(String[] args) {

    //       10
    //     /    \
    //    20    30
    //  /   \
    // 40  60
    Node root = new Node(10);
    root.left = new Node(20);
    root.right = new Node(30);
    root.left.left = new Node(40);
    root.left.right = new Node(60);

    ArrayList<Integer> arr = serialize(root);
    Node res = deSerialize(arr);
}

}

Python

from collections import deque

Node Structure

class Node: def init(self, x): self.data = x self.left = None self.right = None

function to serialize a tree.

def serialize(root): arr = [] q = deque([root])

while q:
    curr = q.popleft()

    # If curr node is null,
    # append -1 to result.
    if not curr:
        arr.append(-1)
        continue
    
    # else push its value into
    # result and push left and right
    # child nodes into queue.
    arr.append(curr.data)
    q.append(curr.left)
    q.append(curr.right)

return arr

function to deserialize a tree.

def deSerialize(arr):

# base case
if arr[0] == -1:
    return None

# create root node and push 
# it into queue
root = Node(arr[0])
q = deque([root])

i = 1
while q:
    curr = q.popleft()

    # If left node is not null
    if arr[i] != -1:
        left = Node(arr[i])
        curr.left = left
        q.append(left)
    i += 1

    # If right node is not null
    if arr[i] != -1:
        right = Node(arr[i])
        curr.right = right
        q.append(right)
    i += 1

return root

if name == "main":

#       10
#     /    \
#    20    30
#  /   \
# 40  60
root = Node(10)
root.left = Node(20)
root.right = Node(30)
root.left.left = Node(40)
root.left.right = Node(60)

arr = serialize(root)
res = deSerialize(arr)

C#

using System; using System.Collections.Generic;

// Node Structure class Node { public int data; public Node left, right; public Node(int x) { data = x; left = null; right = null; } }

class GFG {

//  function to serialize a tree.
static List<int> serialize(Node root) {
    List<int> arr = new List<int>();
    
    Queue<Node> q = new Queue<Node>();
    q.Enqueue(root);
    
    while (q.Count > 0) {
        Node curr = q.Dequeue();
        
        // If curr node is null,
        // append -1 to result.
        if (curr == null) {
            arr.Add(-1);
            continue;
        }
        
        // else push its value into
        // result and push left and right
        // child nodes into queue.
        arr.Add(curr.data);
        
        q.Enqueue(curr.left);
        q.Enqueue(curr.right);
    }
    
    return arr;
}

//  function to deserialize a tree.
static Node deSerialize(List<int> arr) {
    
    // base case
    if (arr[0] == -1) return null;
    
    // create root node and push 
    // it into queue
    Node root = new Node(arr[0]);
    Queue<Node> q = new Queue<Node>();
    q.Enqueue(root);
    
    int i = 1;
    while (q.Count > 0) {
        Node curr = q.Dequeue();
        
        // If left node is not null
        if (arr[i] != -1) {
            Node left = new Node(arr[i]);
            curr.left = left;
            q.Enqueue(left);
        }
        i++;
        
        // If right node is not null
        if (arr[i] != -1) {
            Node right = new Node(arr[i]);
            curr.right = right;
            q.Enqueue(right);
        }
        i++;
    }
    
    return root;
}

static void Main(string[] args) {

    //       10
    //     /    \
    //    20    30
    //  /   \
    // 40   60
    Node root = new Node(10);        
    root.left = new Node(20);        
    root.right = new Node(30);       
    root.left.left = new Node(40);
    root.left.right = new Node(60); 
    
    List<int> arr = serialize(root);
   
    // Variable assigned but never used
    #pragma warning disable CS0219
    Node res = deSerialize(arr);
    #pragma warning restore CS0219
}

}

JavaScript

// Queue node class QNode { constructor(data) { this.data = data; this.next = null; } }

// Custom Queue implementation class Queue { constructor() { this.front = null; this.rear = null; }

isEmpty() {
    return this.front === null;
}

enqueue(x) {
    let newNode = new QNode(x);
    if (this.rear === null) {
        this.front = this.rear = newNode;
        return;
    }
    this.rear.next = newNode;
    this.rear = newNode;
}

dequeue() {
    if (this.front === null)
        return null;

    let temp = this.front;
    this.front = this.front.next;

    if (this.front === null)
        this.rear = null;

    return temp.data;
}

}

// Node Structure class Node { constructor(x) { this.data = x; this.left = null; this.right = null; } }

// function to serialize a tree. function serialize(root) { const arr = []; const q = new Queue();

q.enqueue(root);

while (!q.isEmpty()) {
    const curr = q.dequeue();

    // If curr node is null,
    // append -1 to result.
    if (curr === null) {
        arr.push(-1);
        continue;
    }

    // else push its value into result
    arr.push(curr.data);

    // enqueue children
    q.enqueue(curr.left);
    q.enqueue(curr.right);
}

return arr;

}

// function to deserialize a tree. function deserialize(arr) { if (arr[0] === -1) return null;

const root = new Node(arr[0]);
const q = new Queue();
q.enqueue(root);

let i = 1;
while (!q.isEmpty()) {
    const curr = q.dequeue();

    // Left child
    if (arr[i] !== -1) {
        const left = new Node(arr[i]);
        curr.left = left;
        q.enqueue(left);
    }
    i++;

    // Right child
    if (arr[i] !== -1) {
        const right = new Node(arr[i]);
        curr.right = right;
        q.enqueue(right);
    }
    i++;
}

return root;

}

// Driver Code

// 10 // /
// 20 30 // /
// 40 60

const root = new Node(10); root.left = new Node(20); root.right = new Node(30); root.left.left = new Node(40); root.left.right = new Node(60);

const arr = serialize(root);

const res = deserialize(arr);

`