converting a binary search tree to doubly linked list

ⅰ亾dé卋堺 提交于 2019-12-20 10:55:56

问题


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?


回答1:


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;
    }



回答2:


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);
    }
}



回答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;
 }



回答4:


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




回答5:


A reverse inorder traversal without global variables - c# 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;
}



回答6:


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);
}



回答7:


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;
}



回答8:


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




回答9:


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);
}



回答10:


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);
        }
    }
};



回答11:


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.




回答12:


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);
    }
}


来源:https://stackoverflow.com/questions/11511898/converting-a-binary-search-tree-to-doubly-linked-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!