Convert a given Binary Tree to Doubly Linked List


Convert a given Binary Tree to Doubly Linked List | Set 2 | GeeksforGeeks
https://gist.github.com/gcrfelix/3aeb63a919e0eea6e449
The left and right pointers of binary tree nodes should act as previous and next pointers in doubly linked list and the doubly linked list nodes should follow the same order of nodes as in-order traversal of the tree.
题目:Convert Binary Tree to Circular Doubly LinkedList
具体思路是
1. 拿出根节点。
2. 递归处理left, 找到左边最后一个节点,并且连接root到这个节点上。
3. 递归处理right, 找到右边最前面的节点,并且连接root到这个节点上。
4. return。
最后还需要处理一下头连接到尾巴的双向循环。
https://www.techiedelight.com/place-convert-given-binary-tree-to-doubly-linked-list/


X. https://www.jianshu.com/p/f2eac0a35586
In order traverse this tree.
然后每次返回一个数组,第一位放head of sub tree, 第二位放tail of sub tree
然后注意双向链表的连接。
    private TreeNode[] dfs(TreeNode root) {
        if (root == null)
            return null;
        TreeNode[] left = dfs(root.left);
        TreeNode head = null;
        TreeNode tail = null;
        if (left != null) {
            head = left[0];
            left[1].right = root;
            root.left = left[1];
        }
        TreeNode[] right = dfs(root.right);
        if (right != null) {
            root.right = right[0];
            right[0].left = root;
            tail = right[1];
        }
        TreeNode[] ret = new TreeNode[2];
        ret[0] = (head == null ? root : head);
        ret[1] = (tail == null ? root : tail);
        return ret;
    }

X. Not efficient
https://www.hackingnote.com/en/interview/problems/convert-binary-search-tree-to-doubly-linked-list
https://www.ideserve.co.in/learn/convert-a-binary-tree-to-doubly-linked-list
    public DoublyListNode bstToDoublyList(TreeNode root) {
        // Write your code here
        if (root == null) return null;

        DoublyListNode left = null, right = null;

        if (root.left != null) {
            left = bstToDoublyList(root.left);
        }

        DoublyListNode node = new DoublyListNode(root.val);

        node.prev = rightMost(left);
        if (node.prev != null) {
            node.prev.next = node;
        }

        if (root.right != null) {
            right = bstToDoublyList(root.right);
        }

        node.next = right;
        if (node.next != null) {
            node.next.prev = node;
        }

        return leftMost(node);
    }

    private DoublyListNode leftMost(DoublyListNode node) {
        if (node == null) return null;
        while (node.prev != null) {
            node = node.prev;
        }
        return node;
    }

    private DoublyListNode rightMost(DoublyListNode node) {
        if (node == null) return null;
        while (node.next != null) {
            node = node.next;
        }
        return node;
    }


public class ConvertBTtoCircularDoublyLinkedList {
    public void solve(TreeNode root) {
        if(root == null) {
            return;
        }
        convert(root);
        connectHeadAndTail(root);
    }
 
    public void convert(TreeNode root) {
        if(root == null) {
            return;
        }
        if(root.left != null) {
            TreeNode left = root.left;
            convert(left);
            while(left.right != null) {
                left = left.right;
            }
            left.right = root;
            root.left = left;
        }
        if(root.right != null) {
            TreeNode right = root.right;
            convert(right);
            while(right.left != null) {
                right = right.left;
            }
            right.left = root;
            root.right = right;
        }
    }
 
    public void connectHeadAndTail(TreeNode root) {
        TreeNode head = root;
        while(head.left != null) {
            head = head.left;
        }
        TreeNode tail = root;
        while(tail.right != null) {
            tail = tail.right;
        }
        head.left = tail;
        tail.right = head;
    }
}
Convert a given Binary Tree to Doubly Linked List | Set 3
The idea is to do inorder traversal of the binary tree. While doing inorder traversal, keep track of the previously visited node in a variable say prev. For every visited node, make it next of prev and previous of this node as prev.


Note that use of static variables like above is not a recommended practice (we have used static for simplicity). Imagine a situation where same function is called for two or more trees, the old value of prev would be used in next call for a different tree. To avoid such problems, we can use double pointer or reference to a pointer.
Time Complexity: The above program does a simple inorder traversal, so time complexity is O(n) where n is the number of nodes in given binary tree.
    // head --> Pointer to head node of created doubly linked list
    Node head;
       
    // Initialize previously visited node as NULL. This is
    // static so that the same value is accessible in all recursive
    // calls
    static Node prev = null;
   
    // A simple recursive function to convert a given Binary tree 
    // to Doubly Linked List
    // root --> Root of Binary Tree
    void BinaryTree2DoubleLinkedList(Node root) 
    {
        // Base case
        if (root == null)
            return;
   
        // Recursively convert left subtree
        BinaryTree2DoubleLinkedList(root.left);
   
        // Now convert this node
        if (prev == null
            head = root;
        else
        {
            root.left = prev;
            prev.right = root;
        }
        prev = root;
   
        // Finally convert right subtree
        BinaryTree2DoubleLinkedList(root.right);
    }

Convert a given Binary Tree to Doubly Linked List | Set 2
Time Complexity: O(n) where n is the number of nodes in given Binary Tree. The solution simply does two traversals of all Binary Tree nodes.
1) Fix Left Pointers: In this step, we change left pointers to point to previous nodes in DLL. The idea is simple, we do inorder traversal of tree. In inorder traversal, we keep track of previous visited node and change left pointer to the previous node.
2) Fix Right Pointers
The idea is to use left pointers fixed in step 1. We start from the rightmost node in Binary Tree (BT). The rightmost node is the last node in DLL. Since left pointers are changed to point to previous node in DLL, we can linearly traverse the complete DLL using these pointers. The traversal would be from last to first node. While traversing the DLL, we keep track of the previously visited node and change the right pointer to the previous node. 
// Changes left pointers to work as previous pointers in converted DLL
// The function simply does inorder traversal of Binary Tree and updates
// left pointer using previously visited node
void fixPrevPtr(struct node *root)
{
    static struct node *pre = NULL;
    if (root != NULL)
    {
        fixPrevPtr(root->left);
        root->left = pre;
        pre = root;
        fixPrevPtr(root->right);
    }
}
// Changes right pointers to work as next pointers in converted DLL
struct node *fixNextPtr(struct node *root)
{
    struct node *prev = NULL;
    // Find the right most node in BT or last node in DLL
    while (root && root->right != NULL)
        root = root->right;
    // Start from the rightmost node, traverse back using left pointers.
    // While traversing, change right pointer of nodes.
    while (root && root->left != NULL)
    {
        prev = root;
        root = root->left;
        root->right = prev;
    }
    // The leftmost node is head of linked list, return it
    return (root);
}
// The main function that converts BST to DLL and returns head of DLL
struct node *BTToDLL(struct node *root)
{
    // Set the previous pointer
    fixPrevPtr(root);
    // Set the next pointer and return head of DLL
    return fixNextPtr(root);
}
Convert a given Binary Tree to Doubly Linked List | Set 1
Its not efficient as for every node we go for inorder predecessor and successor!
Time complexity of this code is nLogn.
1. If left subtree exists, process the left subtree
…..1.a) Recursively convert the left subtree to DLL.
…..1.b) Then find inorder predecessor of root in left subtree (inorder predecessor is rightmost node in left subtree).
…..1.c) Make inorder predecessor as previous of root and root as next of inorder predecessor.
2. If right subtree exists, process the right subtree (Below 3 steps are similar to left subtree).
…..2.a) Recursively convert the right subtree to DLL.
…..2.b) Then find inorder successor of root in right subtree (inorder successor is leftmost node in right subtree).
…..2.c) Make inorder successor as next of root and root as previous of inorder successor.
3. Find the leftmost node and return it (the leftmost node is always head of converted DLL).
/* This is the core function to convert Tree to list. This function follows
  steps 1 and 2 of the above algorithm */
node* bintree2listUtil(node* root)
{
    // Base case
    if (root == NULL)
        return root;
    // Convert the left subtree and link to root
    if (root->left != NULL)
    {
        // Convert the left subtree
        node* left = bintree2listUtil(root->left);
        // Find inorder predecessor. After this loop, left
        // will point to the inorder predecessor
        for (; left->right!=NULL; left=left->right);
        // Make root as next of the predecessor
        left->right = root;
        // Make predecssor as previous of root
        root->left = left;
    }
    // Convert the right subtree and link to root
    if (root->right!=NULL)
    {
        // Convert the right subtree
        node* right = bintree2listUtil(root->right);
        // Find inorder successor. After this loop, right
        // will point to the inorder successor
        for (; right->left!=NULL; right = right->left);
        // Make root as previous of successor
        right->left = root;
        // Make successor as next of root
        root->right = right;
    }
    return root;
}
// The main function that first calls bintree2listUtil(), then follows step 3
//  of the above algorithm
node* bintree2list(node *root)
{
    // Base case
    if (root == NULL)
        return root;
    // Convert to DLL using bintree2listUtil()
    root = bintree2listUtil(root);
    // bintree2listUtil() returns root node of the converted
    // DLL.  We need pointer to the leftmost node which is
    // head of the constructed DLL, so move to the leftmost node
    while (root->left != NULL)
        root = root->left;
    return (root);
}
http://www.geeksforgeeks.org/convert-a-given-binary-tree-to-doubly-linked-list-set-4/


In the following implementation, we traverse the tree in inorder fashion. We add nodes at the beginning of current linked list and update head of the list using pointer to head pointer. Since we insert at the beginning, we need to process leaves in reverse order. For reverse order, we first traverse the right subtree before the left subtree. i.e. do a reverse inorder traversal.
    // 'head' - reference to head node of created
    //double linked list
    Node head;
  
    // A simple recursive function to convert a given
    // Binary tree to Doubly Linked List
    void BToDLL(Node root) 
    {
        // Base cases
        if (root == null)
            return;
  
        // Recursively convert right subtree
        BToDLL(root.right);
  
        // insert root into DLL
        root.right = head;
  
        // Change left pointer of previous head
        if (head != null)
            (head).left = root;
  
        // Change head of Doubly linked list
        head = root;
  
        // Recursively convert left subtree
        BToDLL(root.left);
    }
http://fisherlei.blogspot.com/2012/12/leetcode-flatten-binary-tree-to-linked.html
For example, below binary tree.

If we flatten it with in-order, the process should like below. And here I use the left pointer of head node to track the tail node.


1:  TreeNode* flatten(TreeNode *root) {  
2:       if (root == NULL) return NULL;  
3:       TreeNode* rightTree = root->right;  
4:       TreeNode* newHead = root;  
5:       TreeNode* leftList = flatten(root->left);  
6:       if (leftList != NULL)  
7:       {  
8:            newHead = leftList;  
9:            TreeNode* tail = leftList->left;  
10:            tail->right = root;  
11:            root->left = tail;  
12:            leftList->left = root;  
13:       }  
14:       TreeNode* rightList = flatten(rightTree);  
15:       if (rightList != NULL)  
16:       {  
17:            root->right = rightList;  
18:            newHead->left = rightList->left;  
19:            rightList->left = root;  
20:       }  
21:       return newHead;  
22:  } 
http://hehejun.blogspot.com/2015/01/leetcode-flatten-binary-tree-to-doubly_36.html
Postorder反而是这些里面最简单的,因为后序的话不需要考虑备份子节点
如果要constant space的话,类似morris遍历的方法,在每次回收节点的时候,回收的是一个链表上的所有节点,我们只需把链表reverse一样,按照要求连接好,然后连接点之前已经构好的list的末尾就可以了。
public class flattenToDoublyLinkedListAsPostorder {

    private TreeNode head = null;
    private TreeNode tail = null;

    public TreeNode flattenRecursively(TreeNode root) {
        postOrder(root);
        return head;
    }

    private void postOrder(TreeNode node) {
        if (node == null)
            return;
        postOrder(node.left);
        postOrder(node.right);
        if(head == null) {
            head = node;
            head.left = null;
            tail = node;
            tail.right = null;
        } else {
            tail.right = node;
            node.left = tail;
            tail = tail.right;
            tail.right = null;
        }
    }

    public TreeNode flattenIteratively(TreeNode root) {
        if (root == null)
            return null;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode pre = null, head = null, tail = null;
        stack.push(root);
        while(!stack.isEmpty()) {
            TreeNode curr = stack.peek();
            if (isLeaf(curr) || (pre != null && (pre == curr.left || pre == curr.right))) {
                stack.pop();
                if (head == null) {
                    head = curr;
                    tail = curr;
                    head.left = null;
                    head.right = null;
                } else {
                    tail.right = curr;
                    curr.left = tail;
                    tail = tail.right;
                    tail.right = null;
                }
                pre = curr;
            }
            else {
                if (curr.right != null)
                    stack.push(curr.right);
                if (curr.left != null)
                    stack.push(curr.left);
            }
        }
        return head;
    }
}
Flatten Binary Tree to Doubly Linked List As Preorder
这道题是要在flatten to linkedlist的基础上做略微的修改就可以,只要把左指针指向list中前一个node即可.
public class flattenToDoublyLinkedListAsPreorder {
 
    private TreeNode head = null;
    private TreeNode tail = null;
 
    public TreeNode flattenRecursively(TreeNode root) {
        preOrder(root);
        return head;
    }
 
    private void preOrder(TreeNode node) {
        if (node == null)
            return;
        TreeNode leftCopy = node.left;
        TreeNode rightCopy = node.right;
        if(head == null) {
            head = node;
            head.left = null;
            tail = node;
            tail.right = null;
        } else {
            tail.right = node;
            node.left = tail;
            tail = tail.right;
            tail.right = null;
        }
        preOrder(leftCopy);
        preOrder(rightCopy);
    }
 
    public TreeNode flattenIteratively(TreeNode root) {
        TreeNode curr = root, head = null, tail = null;
        Stack<TreeNode> path = new Stack<TreeNode>();
        Stack<TreeNode> rightChildren = new Stack<TreeNode>();
        while (!path.isEmpty() || curr != null) {
            while (curr != null) {
                path.push(curr);
                rightChildren.push(curr.right);
                TreeNode leftCopy = curr.left;
                if (head == null) {
                    head = curr;
                    tail = curr;
                    head.left = null;
                    head.right = null;
                } else {
                    tail.right = curr;
                    curr.left = tail;
                    tail = tail.right;
                    tail.right = null;
                }
                curr = leftCopy;
            }
            path.pop();
            curr = rightChildren.pop();
        }
        return head;
    }
}
[Algorithm] Flatten Binary Tree to Doubly Linked List As Inorder
在preorder递归和迭代版本做略微修改就行了。迭代版本我们第二次访问节点的时候调整左右指针,注意只要备份右指针,然后去到原右子结点。左子节点不需要备份因为之后我们不会去左子树了。递归版本是类似的,只需备份右子结点
public class flattenToDoublyLinkedListAsInorder {

    private TreeNode head = null;
    private TreeNode tail = null;

    public TreeNode flattenRecursively(TreeNode root) {
        InOrder(root);
        return head;
    }

    private void InOrder(TreeNode node) {
        if (node == null)
            return;
        InOrder(node.left);
        TreeNode rightCopy = node.right;
        if(head == null) {
            head = node;
            head.left = null;
            tail = node;
            tail.right = null;
        } else {
            tail.right = node;
            node.left = tail;
            tail = tail.right;
            tail.right = null;
        }
        InOrder(rightCopy);
    }
 
    public TreeNode flattenIteratively(TreeNode root) {
            TreeNode curr = root, head = null, tail = null;
            Stack<TreeNode> path = new Stack<TreeNode>();
            while (!path.isEmpty() || curr != null) {
                    while (curr != null) {
                        path.push(curr);
                        curr = curr.left;
                    }
                    curr = path.pop();
                    TreeNode rightCopy = curr.right;
                    if (head == null) {
                        head = curr;
                        tail = curr;
                        head.left = null;
                        head.right = null;
                    } else {
                        tail.right = curr;
                        curr.left = tail;
                        tail = tail.right;
                        tail.right = null;
                    }
                    curr = rightCopy;
            }
            return head;
        }
}      
Transformation between Binary Tree and Linked Lists
Read full article from Convert a given Binary Tree to Doubly Linked List | Set 2 | GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts