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<queue>#include<vector>usingnamespacestd;classNode{public:intdata;Node*left,*right;Node(intx){data=x;left=right=nullptr;}};// Function to store the preordervoidserializePreOrder(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);returnarr;}// Function to restore the array from preorderNode*deserializePreOrder(int&i,vector<int>&arr){// if element is -1 return nullif(arr[i]==-1){i++;returnnullptr;}// Create the root node.Node*root=newNode(arr[i]);i++;// Create the left and right subtree.root->left=deserializePreOrder(i,arr);root->right=deserializePreOrder(i,arr);returnroot;}Node*deSerialize(vector<int>&arr){inti=0;returndeserializePreOrder(i,arr);}// Function to print preorder traversalvoidpreorder(Node*root){if(root==nullptr)return;cout<<root->data<<" ";preorder(root->left);preorder(root->right);}intmain(){// 10// / \ // 20 30// / \ // 40 60Node*root=newNode(10);root->left=newNode(20);root->right=newNode(30);root->left->left=newNode(40);root->left->right=newNode(60);// Serialize the original treevector<int>arr=serialize(root);// Deserialize the treeNode*res=deSerialize(arr);// Print the deserialized tree in level ordercout<<"[";queue<Node*>q;q.push(res);boolfirst=true;while(!q.empty()){Node*curr=q.front();q.pop();if(curr==nullptr)continue;if(!first)cout<<", ";cout<<curr->data;first=false;q.push(curr->left);q.push(curr->right);}cout<<"]"<<endl;return0;}
Java
importjava.util.*;classNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// Function to store the preordervoidserializePreOrder(Noderoot,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);}// Main function to serialize a tree.ArrayList<Integer>serialize(Noderoot){ArrayList<Integer>arr=newArrayList<>();serializePreOrder(root,arr);returnarr;}// Function to restore the array from preorderNodedeserializePreOrder(int[]i,ArrayList<Integer>arr){// If element is -1, return null.if(arr.get(i[0])==-1){i[0]++;returnnull;}// Create the root node.Noderoot=newNode(arr.get(i[0]));i[0]++;// Create the left and right subtree.root.left=deserializePreOrder(i,arr);root.right=deserializePreOrder(i,arr);returnroot;}NodedeSerialize(ArrayList<Integer>arr){int[]i={0};returndeserializePreOrder(i,arr);}publicstaticvoidmain(String[]args){// 10// / \// 20 30// / \// 40 60Noderoot=newNode(10);root.left=newNode(20);root.right=newNode(30);root.left.left=newNode(40);root.left.right=newNode(60);GFGsol=newGFG();// Serialize the original treeArrayList<Integer>arr=sol.serialize(root);// Deserialize the treeNoderes=sol.deSerialize(arr);// Print the deserialized tree in level orderSystem.out.print("[");Queue<Node>q=newLinkedList<>();q.add(res);booleanfirst=true;while(!q.isEmpty()){Nodecurr=q.poll();if(curr==null)continue;if(!first)System.out.print(", ");System.out.print(curr.data);first=false;q.add(curr.left);q.add(curr.right);}System.out.println("]");}}
Python
fromcollectionsimportdequeclassNode:def__init__(self,data):self.data=dataself.left=Noneself.right=None# Function to store the preorderdefserializePreOrder(root,arr):# Push -1 if root is null.ifrootisNone:arr.append(-1)return# Push the root into result.arr.append(root.data)serializePreOrder(root.left,arr)serializePreOrder(root.right,arr)# Main function to serialize a tree.defserialize(root):arr=[]serializePreOrder(root,arr)returnarr# Function to restore the array from preorderdefdeserializePreOrder(index,arr):# If element is -1, return null.ifarr[index[0]]==-1:index[0]+=1returnNone# Create the root node.root=Node(arr[index[0]])index[0]+=1# Create the left and right subtree.root.left=deserializePreOrder(index,arr)root.right=deserializePreOrder(index,arr)returnrootdefdeSerialize(arr):index=[0]returndeserializePreOrder(index,arr)# Function to print level-order traversaldeflevelOrder(root):ifrootisNone:return[]result=[]q=deque([root])whileq:curr=q.popleft()result.append(curr.data)ifcurr.leftisnotNone:q.append(curr.left)ifcurr.rightisnotNone:q.append(curr.right)returnresultif__name__=="__main__":# 10# / \# 20 30# / \# 40 60root=Node(10)root.left=Node(20)root.right=Node(30)root.left.left=Node(40)root.left.right=Node(60)# Serialize the original treearr=serialize(root)# Deserialize the treeres=deSerialize(arr)# Print the deserialized tree in level orderprint(levelOrder(res))
C#
usingSystem;usingSystem.Collections.Generic;publicclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}publicclassGFG{// Function to store the preordervoidserializePreOrder(Noderoot,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);}// Main function to serialize a tree.publicList<int>serialize(Noderoot){List<int>arr=newList<int>();serializePreOrder(root,arr);returnarr;}// Function to restore the array from preorderNodedeserializePreOrder(refinti,List<int>arr){// If element is -1, return null.if(arr[i]==-1){i++;returnnull;}// Create the root node.Noderoot=newNode(arr[i]);i++;// Create the left and right subtree.root.left=deserializePreOrder(refi,arr);root.right=deserializePreOrder(refi,arr);returnroot;}publicNodedeSerialize(List<int>arr){inti=0;returndeserializePreOrder(refi,arr);}publicstaticvoidMain(){// 10// / \// 20 30// / \// 40 60Noderoot=newNode(10);root.left=newNode(20);root.right=newNode(30);root.left.left=newNode(40);root.left.right=newNode(60);GFGsol=newGFG();// Serialize the original treeList<int>arr=sol.serialize(root);// Deserialize the treeNoderes=sol.deSerialize(arr);// Print the deserialized tree in level orderConsole.Write("[");Queue<Node>q=newQueue<Node>();q.Enqueue(res);boolfirst=true;while(q.Count>0){Nodecurr=q.Dequeue();if(curr==null)continue;if(!first)Console.Write(", ");Console.Write(curr.data);first=false;q.Enqueue(curr.left);q.Enqueue(curr.right);}Console.WriteLine("]");}}
JavaScript
classNode{constructor(data){this.data=data;this.left=null;this.right=null;}}// Function to store the preorderfunctionserializePreOrder(root,arr){if(root===null){arr.push(-1);return;}arr.push(root.data);serializePreOrder(root.left,arr);serializePreOrder(root.right,arr);}// Main function to serialize a treefunctionserialize(root){letarr=[];serializePreOrder(root,arr);returnarr;}// Function to restore the tree from preorderfunctiondeserializePreOrder(i,arr){if(arr[i[0]]===-1){i[0]++;returnnull;}letroot=newNode(arr[i[0]]);i[0]++;root.left=deserializePreOrder(i,arr);root.right=deserializePreOrder(i,arr);returnroot;}functiondeSerialize(arr){leti=[0];returndeserializePreOrder(i,arr);}// Function to print level-order traversalfunctionlevelOrder(root){if(root===null)return[];letresult=[];letq=[root];while(q.length>0){letcurr=q.shift();result.push(curr.data);if(curr.left!==null)q.push(curr.left);if(curr.right!==null)q.push(curr.right);}returnresult;}// Driver code// 10// / \// 20 30// / \// 40 60letroot=newNode(10);root.left=newNode(20);root.right=newNode(30);root.left.left=newNode(40);root.left.right=newNode(60);// Serialize the original treeletarr=serialize(root);// Deserialize the treeletres=deSerialize(arr);// Print the deserialized tree in level orderconsole.log("["+levelOrder(res).join(", ")+"]");
Output
[10, 20, 30, 40, 60]
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.
Serialization: Traverse the tree level by level, storing node values and using -1 for null nodes.
Deserialization: Reconstruct the tree using the stored values and a queue to connect the left and right children.
Let us understand with an example: Input: root = [10, 20, 30, 40, 60, N, N]
The original tree has root 10, children 20 and 30, and children 40 and 60 under node 20.
Serialization visits nodes level by level and stores -1 for null children.
Deserialization uses a queue to restore each node's left and right children.
Serializing the reconstructed tree produces the same serialized array as the original tree.
After removing the -1 markers, the displayed output is [10, 20, 30, 40, 60].
C++
#include<iostream>#include<queue>#include<vector>usingnamespacestd;classNode{public:intdata;Node*left,*right;Node(intx){data=x;left=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);}returnarr;}// function to deserialize a tree.Node*deSerialize(vector<int>&arr){if(arr[0]==-1)returnnullptr;// create root node and push// it into queueNode*root=newNode(arr[0]);queue<Node*>q;q.push(root);inti=1;while(!q.empty()){Node*curr=q.front();q.pop();// If left node is not nullif(arr[i]!=-1){Node*left=newNode(arr[i]);curr->left=left;q.push(left);}i++;// If right node is not nullif(arr[i]!=-1){Node*right=newNode(arr[i]);curr->right=right;q.push(right);}i++;}returnroot;}// Function to print preorder traversalvoidpreorder(Node*root){if(root==nullptr)return;cout<<root->data<<" ";preorder(root->left);preorder(root->right);}intmain(){// 10// / \ // 20 30// / \ // 40 60Node*root=newNode(10);root->left=newNode(20);root->right=newNode(30);root->left->left=newNode(40);root->left->right=newNode(60);// Serialize the original treevector<int>arr=serialize(root);// Deserialize the treeNode*res=deSerialize(arr);// Serialize the deserialized treevector<int>arr2=serialize(res);cout<<"[";boolfirst=true;for(intx:arr2){if(x==-1)continue;if(!first)cout<<", ";cout<<x;first=false;}cout<<"]"<<endl;return0;}
Java
importjava.util.*;classNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// Function to serialize a tree.ArrayList<Integer>serialize(Noderoot){ArrayList<Integer>arr=newArrayList<>();Queue<Node>q=newLinkedList<>();q.add(root);while(!q.isEmpty()){Nodecurr=q.poll();// If curr node is null, append -1.if(curr==null){arr.add(-1);continue;}// Store the node value and add its children.arr.add(curr.data);q.add(curr.left);q.add(curr.right);}returnarr;}// Function to deserialize a tree.NodedeSerialize(ArrayList<Integer>arr){if(arr.get(0)==-1)returnnull;// Create root node and push it into the queue.Noderoot=newNode(arr.get(0));Queue<Node>q=newLinkedList<>();q.add(root);inti=1;while(!q.isEmpty()){Nodecurr=q.poll();// Create the left child if it is not null.if(arr.get(i)!=-1){Nodeleft=newNode(arr.get(i));curr.left=left;q.add(left);}i++;// Create the right child if it is not null.if(arr.get(i)!=-1){Noderight=newNode(arr.get(i));curr.right=right;q.add(right);}i++;}returnroot;}publicstaticvoidmain(String[]args){// 10// / \// 20 30// / \// 40 60Noderoot=newNode(10);root.left=newNode(20);root.right=newNode(30);root.left.left=newNode(40);root.left.right=newNode(60);GFGsol=newGFG();// Serialize the original tree.ArrayList<Integer>arr=sol.serialize(root);// Deserialize the tree.Noderes=sol.deSerialize(arr);// Serialize the deserialized tree.ArrayList<Integer>arr2=sol.serialize(res);System.out.print("[");booleanfirst=true;for(intx:arr2){if(x==-1)continue;if(!first)System.out.print(", ");System.out.print(x);first=false;}System.out.println("]");}}
Python
fromcollectionsimportdequeclassNode:def__init__(self,data):self.data=dataself.left=Noneself.right=None# function to serialize a tree.defserialize(root):arr=[]q=deque([root])whileq:curr=q.popleft()# If curr node is null,# append -1 to result.ifcurrisNone: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)returnarr# function to deserialize a tree.defdeSerialize(arr):ifarr[0]==-1:returnNone# create root node and push# it into queueroot=Node(arr[0])q=deque([root])i=1whileq:curr=q.popleft()# If left node is not nullifarr[i]!=-1:left=Node(arr[i])curr.left=leftq.append(left)i+=1# If right node is not nullifarr[i]!=-1:right=Node(arr[i])curr.right=rightq.append(right)i+=1returnroot# Function to print preorder traversaldefpreorder(root):ifrootisNone:returnprint(root.data,end=" ")preorder(root.left)preorder(root.right)if__name__=="__main__":# 10# / \# 20 30# / \# 40 60root=Node(10)root.left=Node(20)root.right=Node(30)root.left.left=Node(40)root.left.right=Node(60)# Serialize the original treearr=serialize(root)# Deserialize the treeres=deSerialize(arr)# Serialize the deserialized treearr2=serialize(res)print('[',end="")first=Trueforxinarr2:ifx==-1:continueifnotfirst:print(", ",end="")print(x,end="")first=Falseprint(']')
C#
usingSystem;usingSystem.Collections.Generic;publicclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}publicclassGFG{// Function to serialize a tree.publicList<int>serialize(Noderoot){List<int>arr=newList<int>();Queue<Node>q=newQueue<Node>();q.Enqueue(root);while(q.Count>0){Nodecurr=q.Dequeue();// If curr node is null, append -1.if(curr==null){arr.Add(-1);continue;}// Store the node value and add its children.arr.Add(curr.data);q.Enqueue(curr.left);q.Enqueue(curr.right);}returnarr;}// Function to deserialize a tree.publicNodedeSerialize(List<int>arr){if(arr[0]==-1)returnnull;// Create root node and push it into the queue.Noderoot=newNode(arr[0]);Queue<Node>q=newQueue<Node>();q.Enqueue(root);inti=1;while(q.Count>0){Nodecurr=q.Dequeue();// Create the left child if it is not null.if(arr[i]!=-1){Nodeleft=newNode(arr[i]);curr.left=left;q.Enqueue(left);}i++;// Create the right child if it is not null.if(arr[i]!=-1){Noderight=newNode(arr[i]);curr.right=right;q.Enqueue(right);}i++;}returnroot;}publicstaticvoidMain(){// 10// / \// 20 30// / \// 40 60Noderoot=newNode(10);root.left=newNode(20);root.right=newNode(30);root.left.left=newNode(40);root.left.right=newNode(60);GFGsol=newGFG();// Serialize the original tree.List<int>arr=sol.serialize(root);// Deserialize the tree.Noderes=sol.deSerialize(arr);// Serialize the deserialized tree.List<int>arr2=sol.serialize(res);Console.Write("[");boolfirst=true;foreach(intxinarr2){if(x==-1)continue;if(!first)Console.Write(", ");Console.Write(x);first=false;}Console.WriteLine("]");}}
JavaScript
classNode{constructor(data){this.data=data;this.left=null;this.right=null;}}// function to serialize a tree.functionserialize(root){letarr=[];letq=[root];while(q.length>0){letcurr=q.shift();// If curr node is null,// append -1 to result.if(curr===null){arr.push(-1);continue;}// else push its value into// result and push left and right// child nodes into queue.arr.push(curr.data);q.push(curr.left);q.push(curr.right);}returnarr;}// function to deserialize a tree.functiondeSerialize(arr){if(arr[0]===-1){returnnull;}// create root node and push// it into queueletroot=newNode(arr[0]);letq=[root];leti=1;while(q.length>0){letcurr=q.shift();// If left node is not nullif(arr[i]!==-1){letleft=newNode(arr[i]);curr.left=left;q.push(left);}i++;// If right node is not nullif(arr[i]!==-1){letright=newNode(arr[i]);curr.right=right;q.push(right);}i++;}returnroot;}// Function to print preorder traversalfunctionpreorder(root){if(root===null){return;}console.log(root.data+" ");preorder(root.left);preorder(root.right);}// Driver Code// 10// / \// 20 30// / \// 40 60letroot=newNode(10);root.left=newNode(20);root.right=newNode(30);root.left.left=newNode(40);root.left.right=newNode(60);// Serialize the original treeletarr=serialize(root);// Deserialize the treeletres=deSerialize(arr);// Serialize the deserialized treeletarr2=serialize(res);console.log("[");letfirst=true;for(letxofarr2){if(x===-1){continue;}if(!first){console.log(", ");}console.log(x);first=false;}console.log("]");