[Naive Approach] Using Predecessor/Successor Search Recursion - O(n) Time and O(h) Space
The idea is to traverse the binary tree using inorder. At each node, if a left subtree exists, find its inorder predecessor by moving as far right as possible inside the left subtree, then process the left subtree and link the current node with that predecessor. If a right subtree exists, find its inorder successor by moving as far left as possible inside the right subtree, then process the right subtree and link the current node with that successor.
Step by Step Implementation:
If root.left exists, walk right through the left subtree to locate the inorder predecessor of root.
Recursively convert the left subtree, then link the predecessor's right to root and root's left to the predecessor.
If root.right exists, walk left through the right subtree to locate the inorder successor of root.
Recursively convert the right subtree, then link root's right to the successor and the successor's left to root.
Separately, find the head of the DLL by walking all the way left from the original root, since the leftmost node of the tree becomes the head.
C++
#include<iostream>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=nullptr;right=nullptr;}};// Recursively links nodes of the tree in inorder fashionvoidinorder(Node*root){// if left subtree existsif(root->left){// find the inorder predecessor of root nodeNode*pred=root->left;while(pred->right){pred=pred->right;}// process the left subtreeinorder(root->left);// link the predecessor and root nodepred->right=root;root->left=pred;}// if right subtree existsif(root->right){// find the inorder successor of root nodeNode*succ=root->right;while(succ->left){succ=succ->left;}// process the right subtreeinorder(root->right);// link the successor and root noderoot->right=succ;succ->left=root;}}// function to convert binary tree to doubly linked listNode*treeToDLL(Node*root){// return if root is nullif(root==nullptr)returnroot;// find the head of dllNode*head=root;while(head->left!=nullptr)head=head->left;// recursively convert the tree into dllinorder(root);returnhead;}voidprintList(Node*head){// return if list is emptyif(head==nullptr)return;Node*curr=head;// print the list in forward directionwhile(curr->right!=nullptr){cout<<curr->data<<" ";curr=curr->right;}// curr is now at the tail, print the last nodecout<<curr->data<<endl;// print the list in backward directionwhile(curr!=nullptr){cout<<curr->data<<" ";curr=curr->left;}cout<<endl;}intmain(){Node*root=newNode(1);root->left=newNode(2);root->right=newNode(3);Node*head=treeToDLL(root);printList(head);return0;}
Java
classNode{intdata;Nodeleft,right;Node(intx){data=x;left=null;right=null;}}classGfG{// Recursively links nodes of the tree in inorder fashionstaticvoidinorder(Noderoot){// if left subtree existsif(root.left!=null){// find the inorder predecessor of root nodeNodepred=root.left;while(pred.right!=null){pred=pred.right;}// process the left subtreeinorder(root.left);// link the predecessor and root nodepred.right=root;root.left=pred;}// if right subtree existsif(root.right!=null){// find the inorder successor of root nodeNodesucc=root.right;while(succ.left!=null){succ=succ.left;}// process the right subtreeinorder(root.right);// link the successor and root noderoot.right=succ;succ.left=root;}}// function to convert binary tree to doubly linked liststaticNodetreeToDLL(Noderoot){// return if root is nullif(root==null)returnroot;// find the head of dllNodehead=root;while(head.left!=null)head=head.left;// recursively convert the tree into dllinorder(root);returnhead;}staticvoidprintList(Nodehead){// return if list is emptyif(head==null)return;Nodecurr=head;// print the list in forward directionwhile(curr.right!=null){System.out.print(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeSystem.out.println(curr.data);// print the list in backward directionwhile(curr!=null){System.out.print(curr.data+" ");curr=curr.left;}System.out.println();}publicstaticvoidmain(String[]args){Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);Nodehead=treeToDLL(root);printList(head);}}
Python
classNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Recursively links nodes of the tree in inorder fashiondefinorder(root):# if left subtree existsifroot.left:# find the inorder predecessor of root nodepred=root.leftwhilepred.right:pred=pred.right# process the left subtreeinorder(root.left)# link the predecessor and root nodepred.right=rootroot.left=pred# if right subtree existsifroot.right:# find the inorder successor of root nodesucc=root.rightwhilesucc.left:succ=succ.left# process the right subtreeinorder(root.right)# link the successor and root noderoot.right=succsucc.left=root# function to convert binary tree to doubly linked listdeftreeToDLL(root):# return if root is NoneifrootisNone:returnroot# find the head of dllhead=rootwhilehead.left:head=head.left# recursively convert the tree into dllinorder(root)returnheaddefprintList(head):# return if list is emptyifheadisNone:returncurr=head# print the list in forward directionwhilecurr.rightisnotNone:print(curr.data,end=" ")curr=curr.right# curr is now at the tail, print the last nodeprint(curr.data)# print the list in backward directionwhilecurrisnotNone:print(curr.data,end=" ")curr=curr.leftprint()if__name__=="__main__":root=Node(1)root.left=Node(2)root.right=Node(3)head=treeToDLL(root)printList(head)
C#
usingSystem;classNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=null;right=null;}}classGfG{// Recursively links nodes of the tree in inorder fashionstaticvoidinorder(Noderoot){// if left subtree existsif(root.left!=null){// find the inorder predecessor of root nodeNodepred=root.left;while(pred.right!=null){pred=pred.right;}// process the left subtreeinorder(root.left);// link the predecessor and root nodepred.right=root;root.left=pred;}// if right subtree existsif(root.right!=null){// find the inorder successor of root nodeNodesucc=root.right;while(succ.left!=null){succ=succ.left;}// process the right subtreeinorder(root.right);// link the successor and root noderoot.right=succ;succ.left=root;}}// function to convert binary tree to doubly linked liststaticNodetreeToDLL(Noderoot){// return if root is nullif(root==null)returnroot;// find the head of dllNodehead=root;while(head.left!=null)head=head.left;// recursively convert the tree into dllinorder(root);returnhead;}staticvoidprintList(Nodehead){// return if list is emptyif(head==null)return;Nodecurr=head;// print the list in forward directionwhile(curr.right!=null){Console.Write(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeConsole.WriteLine(curr.data);// print the list in backward directionwhile(curr!=null){Console.Write(curr.data+" ");curr=curr.left;}Console.WriteLine();}staticvoidMain(string[]args){Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);Nodehead=treeToDLL(root);printList(head);}}
JavaScript
classNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// Recursively links nodes of the tree in inorder fashionfunctioninorder(root){// if left subtree existsif(root.left){// find the inorder predecessor of root nodeletpred=root.left;while(pred.right){pred=pred.right;}// process the left subtreeinorder(root.left);// link the predecessor and root nodepred.right=root;root.left=pred;}// if right subtree existsif(root.right){// find the inorder successor of root nodeletsucc=root.right;while(succ.left){succ=succ.left;}// process the right subtreeinorder(root.right);// link the successor and root noderoot.right=succ;succ.left=root;}}// function to convert binary tree to doubly linked listfunctiontreeToDLL(root){// return if root is nullif(root===null)returnroot;// find the head of dlllethead=root;while(head.left!==null)head=head.left;// recursively convert the tree into dllinorder(root);returnhead;}functionprintList(head){// return if list is emptyif(head===null)return;letcurr=head;// print the list in forward directionwhile(curr.right!==null){process.stdout.write(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeconsole.log(curr.data);// print the list in backward directionwhile(curr!==null){process.stdout.write(curr.data+" ");curr=curr.left;}console.log();}// Driver Codeletroot=newNode(1);root.left=newNode(2);root.right=newNode(3);lethead=treeToDLL(root);printList(head);
Output
2 1 3
3 1 2
[Better Approach] Single-Pass Inorder Traversal with Previous Pointer Tracking - O(n) Time and O(h) Space
The idea is to do a single inorder traversal of the binary tree while keeping track of the previously visited node in a variable, say prev. For every node visited, link it to prev by setting prev's right to the current node and the current node's left to prev, then update prev to the current node.
Step by Step Implementation:
Maintain two pointers across the recursion: prev, pointing to the last visited node, and head, pointing to the head of the DLL. Pass both by reference so their updates persist across recursive calls.
Recursively process the left subtree first.
If prev is null, the current node is the leftmost node of the tree, so mark it as head. Otherwise, link prev.right to the current node and the current node's left to prev.
Update prev to the current node.
Recursively process the right subtree.
Return head once the whole tree has been traversed.
C++
#include<iostream>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=nullptr;right=nullptr;}};// Recursively links nodes in inorder fashion using a running prev pointervoidinorder(Node*root,Node*&prev,Node*&head){// base caseif(root==nullptr)return;// process the left subtreeinorder(root->left,prev,head);// if prev is null, current node is the leftmost nodeif(prev==nullptr){head=root;}else{// link prev and current nodeprev->right=root;root->left=prev;}// update prev to current nodeprev=root;// process the right subtreeinorder(root->right,prev,head);}// function to convert binary tree to doubly linked listNode*treeToDLL(Node*root){Node*prev=nullptr;Node*head=nullptr;// recursively convert the tree into dllinorder(root,prev,head);returnhead;}voidprintList(Node*head){// return if list is emptyif(head==nullptr)return;Node*curr=head;// print the list in forward directionwhile(curr->right!=nullptr){cout<<curr->data<<" ";curr=curr->right;}// curr is now at the tail, print the last nodecout<<curr->data<<endl;// print the list in backward directionwhile(curr!=nullptr){cout<<curr->data<<" ";curr=curr->left;}cout<<endl;}intmain(){Node*root=newNode(1);root->left=newNode(2);root->right=newNode(3);Node*head=treeToDLL(root);printList(head);return0;}
Java
classNode{intdata;Nodeleft,right;Node(intx){data=x;left=null;right=null;}}classGfG{// Recursively links nodes in inorder fashion using a running prev pointer// prev[0] holds the last visited node, head[0] holds the head of the dllstaticvoidinorder(Noderoot,Node[]prev,Node[]head){// base caseif(root==null)return;// process the left subtreeinorder(root.left,prev,head);// if prev is null, current node is the leftmost nodeif(prev[0]==null){head[0]=root;}else{// link prev and current nodeprev[0].right=root;root.left=prev[0];}// update prev to current nodeprev[0]=root;// process the right subtreeinorder(root.right,prev,head);}// function to convert binary tree to doubly linked liststaticNodetreeToDLL(Noderoot){Node[]prev=newNode[1];Node[]head=newNode[1];// recursively convert the tree into dllinorder(root,prev,head);returnhead[0];}staticvoidprintList(Nodehead){// return if list is emptyif(head==null)return;Nodecurr=head;// print the list in forward directionwhile(curr.right!=null){System.out.print(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeSystem.out.println(curr.data);// print the list in backward directionwhile(curr!=null){System.out.print(curr.data+" ");curr=curr.left;}System.out.println();}publicstaticvoidmain(String[]args){Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);Nodehead=treeToDLL(root);printList(head);}}
Python
classNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Recursively links nodes in inorder fashion using a running prev pointer# prev[0] holds the last visited node, head[0] holds the head of the dlldefinorder(root,prev,head):# base caseifrootisNone:return# process the left subtreeinorder(root.left,prev,head)# if prev is None, current node is the leftmost nodeifprev[0]isNone:head[0]=rootelse:# link prev and current nodeprev[0].right=rootroot.left=prev[0]# update prev to current nodeprev[0]=root# process the right subtreeinorder(root.right,prev,head)# function to convert binary tree to doubly linked listdeftreeToDLL(root):prev=[None]head=[None]# recursively convert the tree into dllinorder(root,prev,head)returnhead[0]defprintList(head):# return if list is emptyifheadisNone:returncurr=head# print the list in forward directionwhilecurr.rightisnotNone:print(curr.data,end=" ")curr=curr.right# curr is now at the tail, print the last nodeprint(curr.data)# print the list in backward directionwhilecurrisnotNone:print(curr.data,end=" ")curr=curr.leftprint()if__name__=="__main__":root=Node(1)root.left=Node(2)root.right=Node(3)head=treeToDLL(root)printList(head)
C#
usingSystem;classNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=null;right=null;}}classGfG{// Recursively links nodes in inorder fashion using a running prev pointerstaticvoidinorder(Noderoot,refNodeprev,refNodehead){// base caseif(root==null)return;// process the left subtreeinorder(root.left,refprev,refhead);// if prev is null, current node is the leftmost nodeif(prev==null){head=root;}else{// link prev and current nodeprev.right=root;root.left=prev;}// update prev to current nodeprev=root;// process the right subtreeinorder(root.right,refprev,refhead);}// function to convert binary tree to doubly linked liststaticNodetreeToDLL(Noderoot){Nodeprev=null;Nodehead=null;// recursively convert the tree into dllinorder(root,refprev,refhead);returnhead;}staticvoidprintList(Nodehead){// return if list is emptyif(head==null)return;Nodecurr=head;// print the list in forward directionwhile(curr.right!=null){Console.Write(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeConsole.WriteLine(curr.data);// print the list in backward directionwhile(curr!=null){Console.Write(curr.data+" ");curr=curr.left;}Console.WriteLine();}staticvoidMain(string[]args){Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);Nodehead=treeToDLL(root);printList(head);}}
JavaScript
classNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// Recursively links nodes in inorder fashion using a running prev pointer// prev and head are wrapper objects so updates persist across recursive callsfunctioninorder(root,prev,head){// base caseif(root===null)return;// process the left subtreeinorder(root.left,prev,head);// if prev is null, current node is the leftmost nodeif(prev.node===null){head.node=root;}else{// link prev and current nodeprev.node.right=root;root.left=prev.node;}// update prev to current nodeprev.node=root;// process the right subtreeinorder(root.right,prev,head);}// function to convert binary tree to doubly linked listfunctiontreeToDLL(root){letprev={node:null};lethead={node:null};// recursively convert the tree into dllinorder(root,prev,head);returnhead.node;}functionprintList(head){// return if list is emptyif(head===null)return;letcurr=head;// print the list in forward directionwhile(curr.right!==null){process.stdout.write(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeconsole.log(curr.data);// print the list in backward directionwhile(curr!==null){process.stdout.write(curr.data+" ");curr=curr.left;}console.log();}// Driver Codeletroot=newNode(1);root.left=newNode(2);root.right=newNode(3);lethead=treeToDLL(root);printList(head);
Output
2 1 3
3 1 2
[Expected Approach] Using Morris Traversal - O(n) Time and O(1) Space
The idea is to use Morris Traversal to traverse the binary tree in inorder fashion while maintaining proper linkages between the nodes, without using recursion or an explicit stack.
Step by Step Implementation:
Initialize pointers head and tail. head will point to the head node of the resultant DLL and tail will point to the last node processed so far in the DLL.
Initialize another pointer curr, which starts at root. Continue traversing until curr is null.
If curr.left is null, link the current node into the DLL (set it as head if the list is still empty), then move curr to curr.right.
If curr.left is not null, find the inorder predecessor of curr, call it pred, by moving right from curr.left until reaching a node whose right pointer is null or already points back to curr.
If pred.right is null, thread it by setting pred.right = curr, then move curr to curr.left.
If pred.right is already curr, the left subtree has been fully processed, so remove the thread, link curr into the DLL, and move curr to curr.right.
Return head.
C++
#include<iostream>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=nullptr;right=nullptr;}};// function to convert binary tree to doubly linked list using morris traversalNode*treeToDLL(Node*root){// return if root is nullif(root==nullptr)returnroot;// head and tail node for the dllNode*head=nullptr;Node*tail=nullptr;Node*curr=root;while(curr!=nullptr){// if left subtree does not exist,// link curr into the dll and move to curr.rightif(curr->left==nullptr){if(head==nullptr){head=tail=curr;}else{tail->right=curr;curr->left=tail;tail=curr;}curr=curr->right;}else{Node*pred=curr->left;// find the inorder predecessor of currwhile(pred->right!=nullptr&&pred->right!=curr){pred=pred->right;}// create a thread from pred to currif(pred->right==nullptr){pred->right=curr;curr=curr->left;}else{// left subtree processed, remove the thread,// link curr into the dll and move to curr.rightpred->right=nullptr;tail->right=curr;curr->left=tail;tail=curr;curr=curr->right;}}}returnhead;}voidprintList(Node*head){// return if list is emptyif(head==nullptr)return;Node*curr=head;// print the list in forward directionwhile(curr->right!=nullptr){cout<<curr->data<<" ";curr=curr->right;}// curr is now at the tail, print the last nodecout<<curr->data<<endl;// print the list in backward directionwhile(curr!=nullptr){cout<<curr->data<<" ";curr=curr->left;}cout<<endl;}intmain(){Node*root=newNode(1);root->left=newNode(2);root->right=newNode(3);Node*head=treeToDLL(root);printList(head);return0;}
Java
classNode{intdata;Nodeleft,right;Node(intx){data=x;left=null;right=null;}}classGfG{// function to convert binary tree to doubly linked list using morris traversalstaticNodetreeToDLL(Noderoot){// return if root is nullif(root==null)returnroot;// head and tail node for the dllNodehead=null;Nodetail=null;Nodecurr=root;while(curr!=null){// if left subtree does not exist,// link curr into the dll and move to curr.rightif(curr.left==null){if(head==null){head=tail=curr;}else{tail.right=curr;curr.left=tail;tail=curr;}curr=curr.right;}else{Nodepred=curr.left;// find the inorder predecessor of currwhile(pred.right!=null&&pred.right!=curr){pred=pred.right;}// create a thread from pred to currif(pred.right==null){pred.right=curr;curr=curr.left;}else{// left subtree processed, remove the thread,// link curr into the dll and move to curr.rightpred.right=null;tail.right=curr;curr.left=tail;tail=curr;curr=curr.right;}}}returnhead;}staticvoidprintList(Nodehead){// return if list is emptyif(head==null)return;Nodecurr=head;// print the list in forward directionwhile(curr.right!=null){System.out.print(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeSystem.out.println(curr.data);// print the list in backward directionwhile(curr!=null){System.out.print(curr.data+" ");curr=curr.left;}System.out.println();}publicstaticvoidmain(String[]args){Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);Nodehead=treeToDLL(root);printList(head);}}
Python
classNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# function to convert binary tree to doubly linked list using morris traversaldeftreeToDLL(root):# return if root is NoneifrootisNone:returnroot# head and tail node for the dllhead=Nonetail=Nonecurr=rootwhilecurrisnotNone:# if left subtree does not exist,# link curr into the dll and move to curr.rightifcurr.leftisNone:ifheadisNone:head=tail=currelse:tail.right=currcurr.left=tailtail=currcurr=curr.rightelse:pred=curr.left# find the inorder predecessor of currwhilepred.rightisnotNoneandpred.right!=curr:pred=pred.right# create a thread from pred to currifpred.rightisNone:pred.right=currcurr=curr.leftelse:# left subtree processed, remove the thread,# link curr into the dll and move to curr.rightpred.right=Nonetail.right=currcurr.left=tailtail=currcurr=curr.rightreturnheaddefprintList(head):# return if list is emptyifheadisNone:returncurr=head# print the list in forward directionwhilecurr.rightisnotNone:print(curr.data,end=" ")curr=curr.right# curr is now at the tail, print the last nodeprint(curr.data)# print the list in backward directionwhilecurrisnotNone:print(curr.data,end=" ")curr=curr.leftprint()if__name__=="__main__":root=Node(1)root.left=Node(2)root.right=Node(3)head=treeToDLL(root)printList(head)
C#
usingSystem;classNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=null;right=null;}}classGfG{// function to convert binary tree to doubly linked list using morris traversalstaticNodetreeToDLL(Noderoot){// return if root is nullif(root==null)returnroot;// head and tail node for the dllNodehead=null;Nodetail=null;Nodecurr=root;while(curr!=null){// if left subtree does not exist,// link curr into the dll and move to curr.rightif(curr.left==null){if(head==null){head=tail=curr;}else{tail.right=curr;curr.left=tail;tail=curr;}curr=curr.right;}else{Nodepred=curr.left;// find the inorder predecessor of currwhile(pred.right!=null&&pred.right!=curr){pred=pred.right;}// create a thread from pred to currif(pred.right==null){pred.right=curr;curr=curr.left;}else{// left subtree processed, remove the thread,// link curr into the dll and move to curr.rightpred.right=null;tail.right=curr;curr.left=tail;tail=curr;curr=curr.right;}}}returnhead;}staticvoidprintList(Nodehead){// return if list is emptyif(head==null)return;Nodecurr=head;// print the list in forward directionwhile(curr.right!=null){Console.Write(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeConsole.WriteLine(curr.data);// print the list in backward directionwhile(curr!=null){Console.Write(curr.data+" ");curr=curr.left;}Console.WriteLine();}staticvoidMain(string[]args){Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);Nodehead=treeToDLL(root);printList(head);}}
JavaScript
classNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// function to convert binary tree to doubly linked list using morris traversalfunctiontreeToDLL(root){// return if root is nullif(root===null)returnroot;// head and tail node for the dlllethead=null;lettail=null;letcurr=root;while(curr!==null){// if left subtree does not exist,// link curr into the dll and move to curr.rightif(curr.left===null){if(head===null){head=tail=curr;}else{tail.right=curr;curr.left=tail;tail=curr;}curr=curr.right;}else{letpred=curr.left;// find the inorder predecessor of currwhile(pred.right!==null&&pred.right!==curr){pred=pred.right;}// create a thread from pred to currif(pred.right===null){pred.right=curr;curr=curr.left;}else{// left subtree processed, remove the thread,// link curr into the dll and move to curr.rightpred.right=null;tail.right=curr;curr.left=tail;tail=curr;curr=curr.right;}}}returnhead;}functionprintList(head){// return if list is emptyif(head===null)return;letcurr=head;// print the list in forward directionwhile(curr.right!==null){process.stdout.write(curr.data+" ");curr=curr.right;}// curr is now at the tail, print the last nodeconsole.log(curr.data);// print the list in backward directionwhile(curr!==null){process.stdout.write(curr.data+" ");curr=curr.left;}console.log();}// Driver Codeletroot=newNode(1);root.left=newNode(2);root.right=newNode(3);lethead=treeToDLL(root);printList(head);