7

This question was asked in a recent coding interview.

Q : Given a binary tree, write a program to convert it to a doubly linked list. The nodes in the doubly linked list are arranged in a sequence formed by a zig-zag level order traversal

My approach

i could always do the zig-zag level order traversal of the tree and store it in an array an then make a double linked list. but the question demands for a in-place solution. can anyone help in explaining the recursive approach should be used?

NoobEditor
  • 15,563
  • 19
  • 81
  • 112
akash
  • 1,801
  • 7
  • 24
  • 42
  • 12
    As a side note, what an awful interview question. – corsiKa Jul 16 '12 at 20:22
  • First: perform rotations and strech into a linked-list. second: set the backpointers. (maybe you could combine the steps, but I am too lazy to do your homework) And, indeed: it is a terrible non-problem. – wildplasser Jul 16 '12 at 20:26
  • @wildplasser can you please elaborate . thanks for the reply – akash Jul 16 '12 at 20:28
  • 2
    @wildplasser - OP clearly has a tag of interview-questions. NOT Homework. We can be more accomodating and less snarky in commenting and helping if we have time and are not lazy, if not pass it on. – goldenmean Jul 17 '12 at 20:46
  • 1
    @corsika awful yes, but it is being asked in one of the top companies, what option do we have here? If we like to work for them. – flash Mar 05 '13 at 05:40
  • Btw, the title says binary search tree and I don't think the solution changes from what works for any binary tree. – Swapnil Sep 05 '14 at 17:33
  • You could still do a BFS search but not store everything in an array. Is the recursive method still considered in place if you are growing the stack? – user2233706 May 19 '16 at 19:20

14 Answers14

13

This is the recursive approach.Note that ,here root will point to some inbetween element of the list formed. So,just traverse from root backwards to get the head.

#define NODEPTR struct node*

NODEPTR convert_to_ll(NODEPTR root){
    if(root->left == NULL && root->right == NULL)
        return root;
    NODEPTR temp = NULL;
    if(root->left != NULL){
        temp = convert_to_ll(root->left);
        while(temp->right != NULL)
            temp = temp->right;
        temp->right = root;
        root->left = temp;
    }
    if(root->right != NULL){
        temp = convert_to_ll(root->right);
        while(temp->left != NULL)
            temp = temp->left;
        temp->left = root;
        root->right = temp;
    }
    return root;
    }
vagrawal13
  • 475
  • 2
  • 6
  • 15
4

Simplest method. In single inorder traversal and with just O(1) space complexity we can achieve this. Keep a pointer named lastPointer and keep track of it after visiting every node. use left and right

public void toll(T n) {
    if (n != null) {
        toll(n.left);
        if(lastPointer==null){
            lastPointer=n;
        }else{
            lastPointer.right=n;
            n.left=lastPointer;
            lastPointer=n;
        }
        toll(n.right);
    }
}
Codex
  • 1,153
  • 1
  • 20
  • 31
3

C++ code:

 Node<T> *BTtoDoublyLLZigZagOrder(Node<T> *root)
 {
        if (root == 0)
            return 0;
        if (root->mLeft == 0 && root->mRight == 0)
            return root;

        queue<Node<T> *> q;
        q.push(root);
        Node<T> *head = root;
        Node<T> *prev = 0,*curr = 0;

        while(!q.empty())
        {
            curr = q.front();
            q.pop();
            if (curr->mLeft)
                q.push(curr->mLeft);
            if (curr->mRight)
                q.push(curr->mRight);
            curr->mRight = q.front();
            curr->mLeft = prev;
            prev = curr;
        }

        return head;
 }
Sungguk Lim
  • 6,109
  • 7
  • 43
  • 63
ami
  • 31
  • 1
  • Although the code is quite readable, would probably be best to add a pseudo code version or an explanation of technique, as the question was language agnostic. – Orbling Nov 26 '12 at 15:28
2

The solution mentioned in the stanford library link is perfect solution for BST to circular DLL, below solution is not exactly the conversion of BST to circular DLL but Circular DLL can be achieved by joining ends of a DLL. Its not exactly the zig zag ordered tree to dll conversion too.

NOTE : this solution is not perfect conversion from BST to circular DLL but its an easily understandable hack

JAVA code

public Node bstToDll(Node root ){
        if(root!=null){
            Node lefthead = bstToDll(root.left); // traverse down to left 
            Node righthead = bstToDll(root.right); // traverse down to right
            Node temp = null;
            /*
             * lefthead represents head of link list created in left of node
             * righthead represents head of link list created in right
             * travel to end of left link list and add the current node in end
             */
            if(lefthead != null) {
                temp = lefthead;
                while(temp.next != null){
                    temp = temp.next;
                }
                temp.next = root;
            }else{
                lefthead = root;
            }
            root.prev = temp;
            /*
             *set the next node of current root to right head of right list
             */
            if(righthead != null){
                root.next = righthead;
                righthead.prev = root;
            }else{
                righthead = root;
            }
            return lefthead;// return left head as the head of the list added with current node
        }
        return null;
}

Hope it helps some one

NoobEditor
  • 15,563
  • 19
  • 81
  • 112
Anupam Gupta
  • 1,591
  • 8
  • 36
  • 60
1

A reverse inorder traversal without global variables - implementation. While calling, null will be passed to the right parameter initially. The final return value is the head of the doubly linked list

public static Node ToDLL(Node node, Node right)
{
    if (node == null)
        return null;

    var rnd = ToDLL(node.Right, right);

    if (rnd != null)
    {
        node.Right = rnd;
        rnd.Left = node;
    }
    else
    {
        node.Right = right;
        if (right!= null)
            right.Left= node;
    }
    return ToDLL(node.Left, node) ?? node;
}
Saravanan
  • 920
  • 9
  • 22
0

We will use two sentinel nodes head and tail and do an in-order traversal of the tree. First time we have to link the head to the smallest node and vice-versa and also link the smallest node to tail and vice-versa. After the first time we will only need to re-link current-node and tail until the traversal is completed. Post traversal we will remove the sentinel nodes and re-link the head and tail properly.

public static Node binarySearchTreeToDoublyLinkedList(Node root) {

    // sentinel nodes
    Node head = new Node();
    Node tail = new Node();

    // in-order traversal
    binarySearchTreeToDoublyLinkedList(root, head, tail);

    // re-move the sentinels and re-link;
    head = head.right;
    tail = tail.left;

    if (head != null && tail != null) {
        tail.right = head;
        head.left = tail;
    }

    return head;
}

/** In-order traversal **/
private static void binarySearchTreeToDoublyLinkedList(Node currNode, Node head, Node tail) {
    if (currNode == null) {
        return;
    }


    // go left
    //

    binarySearchTreeToDoublyLinkedList(currNode.left, head, tail);

    // save right node for right traversal as we will be changing current
    // node's right to point to tail
    //

    Node right = currNode.right;

    // first time
    //

    if (head.right == null) {

        // fix head
        //

        head.right = currNode;
        currNode.left = head;

        // fix tail
        //

        tail.left = currNode;
        currNode.right = tail;

    } else {

        // re-fix tail
        //

        Node prev = tail.left;

        // fix current and tail
        //

        tail.left = currNode;
        currNode.right = tail;

        // fix current and previous
        //

        prev.right = currNode;
        currNode.left = prev;
    }

    // go right
    //

    binarySearchTreeToDoublyLinkedList(right, head, tail);
}
0
node* convertToDLL(node* root, node*& head, node*& tail)
{
    //empty tree passed in, nothing to do
    if(root == NULL)
        return NULL;

    //base case
    if(root->prev == NULL && root->next == NULL)
        return root;

    node* temp = NULL;
    if(root->prev != NULL)
    {
        temp = convertToDLL(root->prev, head, tail);

        //new head of the final list, this will be the left most
        //node of the tree.
        if(head == NULL)
        {
            head=temp;
            tail=root;
        }

        //create the DLL of the left sub tree, and update t
        while(temp->next != NULL)
            temp = temp->next;
        temp->next = root;
        root->prev= temp;
        tail=root;
    }

    //create DLL for right sub tree
    if(root->next != NULL)
    {
        temp = convertToDLL(root->next, head, tail);
        while(temp->prev != NULL)
            temp = temp->prev;
        temp->prev = root;
        root->next = temp;

        //update the tail, this will be the node with the largest value in
        //right sub tree
        if(temp->next && temp->next->val > tail->val)
            tail = temp->next;
        else if(temp->val > tail->val)
            tail = temp;
    }
    return root;
}

void createCircularDLL(node* root, node*& head, node*& tail)
{
    convertToDLL(root,head,tail);

    //link the head and the tail
    head->prev=tail;
    tail->next=head;
}

int main(void)
{

    //create a binary tree first and pass in the root of the tree......
    node* head = NULL;
    node* tail = NULL;
    createCircularDLL(root, head,tail);

    return 1;
}
gilla07
  • 61
  • 2
0
struct node{
int value;
struct node *left;
struct node *right;
};
typedef struct node Node;

Node * create_node(int value){
  Node * temp =  (Node *)malloc(sizeof(Node));
  temp->value = value;
  temp->right= NULL;
  temp->left = NULL;
  return temp;
}
Node * addNode(Node *node, int value){
  if(node == NULL){
    return create_node(value);
  }
  else{
    if (node->value > value){
        node->left = addNode(node->left, value);
    }
    else{
        node->right = addNode(node->right, value);
    }
  }
  return node;
}

void treeToList(Node *node){

    Queue *queue = NULL;
    Node * last = NULL;
    if(node == NULL)
            return ;

    enqueue(&queue, node);
    while(!isEmpty(queue)){
       /* Take the first element and put 
          both left and right child on queue */
            node = front(queue);
            if(node->left)
                    enqueue(&queue, node->left);
            if(node->right)
                    enqueue(&queue, node->right);
            if(last != NULL)
                    last->right = node;
            node->left = last;
            last = node;
            dequeue(&queue);
      }
  } 
  /* Driver program for the function written above */
 int main(){
    Node *root = NULL;
   //Creating a binary tree
    root = addNode(root,30);
    root = addNode(root,20);
    root = addNode(root,15);
    root = addNode(root,25);
    root = addNode(root,40);
    root = addNode(root,37);
    root = addNode(root,45);

    treeToList(root);

    return 0;
}

Implementation of queue APIs can be found at http://www.algorithmsandme.com/2013/10/binary-search-tree-to-doubly-linked.html

jitsceait
  • 11
  • 3
0

We can use inorder traversal and keep track of the previously visited node. For every visited node, previous node right and current node left can be assigned.

void BST2DLL(node *root, node **prev, node **head)
{
    // Base case
    if (root == NULL) return;

    // Recursively convert left subtree
    BST2DLL(root->left, prev, head);

    if (*prev == NULL) // first iteration
        *head = root;
    else
    {
        root->left = *prev;
        (*prev)->right = root;
    }
    *prev = root; // save the prev pointer 

    // Finally convert right subtree
    BST2DLL(root->right, prev, head);
}
learner
  • 123
  • 2
  • 11
0

Hope this will help u.

class Solution(){
public:
    TreeNode* convertBST2DLL(TreeNode* root){
        TreeNode left, right;
        convert(root, &left, &right);
        TreeNode* head = left.right;
        head->left = NULL;
        right.left->right = NULL;
        return head;
    }   
    void convert(TreeNode* root, TreeNode* left, TreeNode* right){
        if(root->left == NULL){
            left->right = root;
            root->left = left;
        }
        else{
            convert(root->left, left, root);
        }
        if(root->right == NULL){
            right->left = root;
            root->right = right;
        }
        else{
            convert(root->right, root, right);
        }
    }
};
0

I realize this is quite old, but I was solving this in preparation for interviews, and I realized if you think about each recursive function call taking in, updating and returning the current head of the linked list, it is much simpler. It's also better to use reverse order traversal if you are interested in returning the head. Passing the head into the recursive function also keeps from needing a static or global variable. Here's the Python code:

def convert(n, head=None):
  if n.right:
    head = convert(n.right, head)
  if head:
    head.left = n
  n.right = head
  if n.left:
    head = convert(n.left, n)
  else:
    head = n
  return head

Hope this is of use to someone.

DavidMFrey
  • 1,658
  • 1
  • 14
  • 14
0

Here is Java code. Complexity is O(N). I also add some test cases for this problem.

public class BinaryToDoubleLinkedList {

    static class Node {
        int value;
        Node left;
        Node right;

        public Node(int value, Node left, Node right) {
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }

    static class Pair {
        Node head;
        Node tail;

        public Pair(Node head, Node tail) {
            this.head = head;
            this.tail = tail;
        }
    }

    static Pair convertToDoubleLinkedList(Node root) {
        return convert(root);
    }

    static Pair convert(Node root) {
        if (root == null) return new Pair(null, null);

        Node head, last;

        Pair left = convert(root.left);
        if (left.tail != null) {
            left.tail.right = root;
            root.left = left.tail;
            head = left.head;
        } else {
            head = root;
        }

        Pair right = convert(root.right);
        if (right.head != null) {
            right.head.left = root;
            root.right = right.head;
            last = right.tail;
        } else {
            last = root;
        }

        return new Pair(head, last);
    }

    static void Print(Node root, boolean fromLeft) {
        System.out.println("---------");
        if (fromLeft) {
            while (root != null) {
                System.out.print(root.value + ",");
                root = root.right;
            }
        } else {
            while (root != null) {
                System.out.print(root.value + ",");
                root = root.left;
            }
        }

        System.out.println();
    }

    public static void main(String[] args) {
        test1();
        test2();
        test3();
    }

    // test 1: normal test case
    public static void test1() {
        Node root = new Node(10, null, null);
        root.left = new Node(12, null, null);
        root.right = new Node(15, null, null);

        root.left.left = new Node(25, null, null);
        root.left.right = new Node(30, null, null);
        root.right.left = new Node(36, null, null);

        Pair res = convertToDoubleLinkedList(root);
        Print(res.head, true);
        Print(res.tail, false);
    }

    // test 2: binary tree as linked list
    public static void test2() {
        Node root = new Node(1, null, null);
        root.left = new Node(2, null, null);
        root.left.left = new Node(3, null, null);
        root.left.left.left = new Node(4, null, null);

        Pair res = convertToDoubleLinkedList(root);
        Print(res.head, true);
        Print(res.tail, false);
    }

    // test 3: null and single
    public static void test3() {
        Node root = new Node(1, null, null);
        Pair res = convertToDoubleLinkedList(root);
        Print(res.head, true);
        Print(res.tail, false);

        res = convertToDoubleLinkedList(null);
        Print(res.head, true);
        Print(res.tail, false);
    }
}
hqt
  • 29,632
  • 51
  • 171
  • 250
0

Finding the in-order predecessor and pointing the left and right to the predecessor of the current root will do the job for you. The time complexity to run the below code is O(N) and will take the auxiliary space O(H), where H = Height of the Tree, being implicitly used for the recursion stack. The below code is written using Python 3.

def convertToDLL(root):
    # Base check
    if root is None:
        return root

    # Converting left sub-tree to root
    if root.left:

        # Convert the left subtree
        left = convertToDLL(root.left)

        while left.right:
            left = left.right

        left.right = root
        root.left = left

    # Converting right sub-tree to root
    if root.right:

        # Convert the right subtree
        right = convertToDLL(root.right)

        while right.left:
            right = right.left

        right.left = root
        root.right = right

    return root


def bToDLL(root):
    if root is None:
        return root

    # Convert to DLL
    root = convertToDLL(root)

    while root.left:
        root = root.left

    return root


def display(head):
    # Display
    if head is None:
        return
    while head:
        print(head.data, end=" ")
        head = head.right
LITDataScience
  • 380
  • 5
  • 14
0

Steps:

  1. Inorder traversal of the tree

  2. During the node processing step, keep track of head and tail and keep incrementing the tail

  3. Reconnect head and tail at the end

      def binarysearchtreeToLL(root):  
         def dfsInorder(node):  
             nonlocal head, tail 
    
             if not node:  
                 return None  
    
             dfsInorder(node.left)  
    
             if tail:  
                  tail.right = node  
                   node.left = tail  
              else:  
                   head = node  
              tail = node  
    
              dfsInorder(node.right)  
    
          if not root:  
              return None  
          head, tail = None, None  
          dfsInorder(root)  
          head.left = tail  
          tail.right = head  
          return head  
    

Time Complexity: O(n) Space Complexity: O(n) in worst case where n recursion stack calls are made.

annakun
  • 1
  • 1