Open In App

Serialize and Deserialize a Binary Tree

Last Updated : 04 Oct, 2025
Suggest changes
Share
Like Article
Like
Report

Given the root of a binary tree, Complete the functions:

  • serialize(): Traverse the tree, store node values in an array, and insert -1 wherever a node is null. Returns the array representing the tree.
  • deSerialize(): Read the values of the array arr[] to reconstruct the tree. An element arr[i] == -1 represents a missing (null) child.

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

[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.

  • Serialization: Perform preorder traversal, store node values and insert -1 wherever a node is null.
  • Deserialization: Rebuild the tree by reading values in preorder order. If the value is -1, return null. Otherwise, create a node and recursively build its left and right children.

Pseudo-code Idea (Deserialization)

  • If current value = -1 → return NULL
  • Else Create a new node with the current value
  • Recursively call to build node->left and node->right
  • Return the node
C++
#include <iostream> #include<vector> #include<queue> 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<int> &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<int> serialize(Node *root) {  vector<int> arr;  serializePreOrder(root, arr);  return arr; } // Function to restore the array from preorder Node* deserializePreOrder(int &i, vector<int> &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<int> &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 <iostream> #include <vector> #include <queue> 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<int> serialize(Node *root) {  vector<int> 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<int> &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); 



Explore