📜  将给定的二叉树转换为双向链表 |设置 3

📅  最后修改于: 2022-05-13 01:57:19.970000             🧑  作者: Mango

将给定的二叉树转换为双向链表 |设置 3

给定一个二叉树 (BT),将其就地转换为双向链表 (DLL)。节点中的左指针和右指针分别用作转换后的DLL中的前一个指针和下一个指针。对于给定的二叉树,DLL 中的节点顺序必须与 Inorder 中的相同。 Inorder遍历的第一个节点(BT中最左边的节点)必须是DLL的头节点。

树到列表

针对这个问题讨论了以下两种不同的解决方案。
将给定的二叉树转换为双向链表 |设置 1
将给定的二叉树转换为双向链表 |设置 2

在这篇文章中,讨论了第三种解决方案,这似乎是最简单的。这个想法是按顺序遍历二叉树。在进行中序遍历时,在变量中跟踪先前访问过的节点,比如prev 。对于每个访问过的节点,将其设置为该节点的prevprev旁边。
感谢 rahul、wishall 和所有其他读者对上述两篇文章的有用评论。

以下是该解决方案的实现。

C++
// A C++ program for in-place conversion of Binary Tree to DLL
#include 
using namespace std;
 
/* A binary tree node has data, and left and right pointers */
struct node
{
    int data;
    node* left;
    node* right;
};
 
// A simple recursive function to convert a given Binary tree to Doubly
// Linked List
// root --> Root of Binary Tree
// head --> Pointer to head node of created doubly linked list
void BinaryTree2DoubleLinkedList(node *root, node **head)
{
    // Base case
    if (root == NULL) return;
 
    // Initialize previously visited node as NULL. This is
    // static so that the same value is accessible in all recursive
    // calls
    static node* prev = NULL;
 
    // Recursively convert left subtree
    BinaryTree2DoubleLinkedList(root->left, head);
 
    // 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, head);
}
 
/* Helper function that allocates a new node with the
   given data and NULL left and right pointers. */
node* newNode(int data)
{
    node* new_node = new node;
    new_node->data = data;
    new_node->left = new_node->right = NULL;
    return (new_node);
}
 
/* Function to print nodes in a given doubly linked list */
void printList(node *node)
{
    while (node!=NULL)
    {
        cout << node->data << " ";
        node = node->right;
    }
}
 
/* Driver program to test above functions*/
int main()
{
    // Let us create the tree shown in above diagram
    node *root        = newNode(10);
    root->left        = newNode(12);
    root->right       = newNode(15);
    root->left->left  = newNode(25);
    root->left->right = newNode(30);
    root->right->left = newNode(36);
 
    // Convert to DLL
    node *head = NULL;
    BinaryTree2DoubleLinkedList(root, &head);
 
    // Print the converted list
    printList(head);
 
    return 0;
}


Java
// A Java program for in-place conversion of Binary Tree to DLL
  
// A binary tree node has data, left pointers and right pointers
class Node
{
    int data;
    Node left, right;
  
    public Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
  
class BinaryTree
{
    Node root;
      
    // 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);
    }
  
    /* Function to print nodes in a given doubly linked list */
    void printList(Node node)
    {
        while (node != null)
        {
            System.out.print(node.data + " ");
            node = node.right;
        }
    }
  
    // Driver program to test above functions
    public static void main(String[] args)
    {
        // Let us create the tree as shown in above diagram
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(10);
        tree.root.left = new Node(12);
        tree.root.right = new Node(15);
        tree.root.left.left = new Node(25);
        tree.root.left.right = new Node(30);
        tree.root.right.left = new Node(36);
  
        // convert to DLL
        tree.BinaryTree2DoubleLinkedList(tree.root);
          
        // Print the converted List
        tree.printList(tree.head);
  
    }
}
// This code has been contributed by Mayank Jaiswal(mayank_24)


Python3
# Python program for conversion of
# binary tree to doubly linked list.
class Node:
    def __init__(self, val):
        self.right = None
        self.data = val
        self.left = None
 
 
class BtoDll:
    def __init__(self):
        self.head = None
        self.tail = None
 
    def convert(self, root):
       
        # Base case
        if root is None:
            return
           
        # Recursively convert left subtree
        self.convert(root.left)
         
        # Now convert this node
        node = root
        if self.head is None:
            self.head = node
        else:
            self.tail.right = node
            node.left = self.tail
        self.tail = node
         
        # Finally convert right subtree
        self.convert(root.right)
        return self.head
 
 
def BinaryTree2DoubleLinkedList(root):
    '''
    A simple recursive function to convert a given Binary tree 
    to Doubly Linked List
    root --> Root of Binary Tree
    '''
    converter = BtoDll()
    return converter.convert(root)
 
 
def print_dll(head):
    '''Function to print nodes in given doubly linked list'''
    while head is not None:
        print(head.data, end=" ")
        head = head.right
 
 
#  Driver program to test above functions
if __name__ == "__main__":
   
    # Let us create the tree as
    # shown in above diagram
    root = Node(10)
    root.left = Node(12)
    root.right = Node(15)
    root.left.left = Node(25)
    root.left.right = Node(30)
    root.right.left = Node(36)
     
    # convert to DLL
    head = BinaryTree2DoubleLinkedList(root)
     
    # Print the converted list
    print_dll(head)
     
# This code is contributed by codesankalp (SANKALP)


C#
// A C# program for in-place conversion
// of Binary Tree to DLL
using System;
 
// A binary tree node has data, left
// pointers and right pointers
public class Node
{
    public int data;
    public Node left, right;
 
    public Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
 
class GFG
{
public Node root;
 
// head --> Pointer to head node of
// created doubly linked list
public Node head;
 
// Initialize previously visited node
// as NULL. This is static so that the
// same value is accessible in all
// recursive calls
public static Node prev = null;
 
// A simple recursive function to
// convert a given Binary tree
// to Doubly Linked List
// root --> Root of Binary Tree
public virtual 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);
}
 
/* Function to print nodes in a
   given doubly linked list */
public virtual void printList(Node node)
{
    while (node != null)
    {
        Console.Write(node.data + " ");
        node = node.right;
    }
}
 
// Driver Code
public static void Main(string[] args)
{
    // Let us create the tree as
    // shown in above diagram
    GFG tree = new GFG();
    tree.root = new Node(10);
    tree.root.left = new Node(12);
    tree.root.right = new Node(15);
    tree.root.left.left = new Node(25);
    tree.root.left.right = new Node(30);
    tree.root.right.left = new Node(36);
 
    // convert to DLL
    tree.BinaryTree2DoubleLinkedList(tree.root);
 
    // Print the converted List
    tree.printList(tree.head);
 
}
}
 
// This code is contributed by Shrikant13


Javascript


C++
Node * bToDLL(Node *root)
{
    stack> s;
    s.push({root, 0});
    vector res;
    bool flag = true;
    Node* head = NULL;
    Node* prev = NULL;
    while(!s.empty()) {
        auto x = s.top();
        Node* t = x.first;
        int state = x.second;
        s.pop();
        if(state == 3 or t == NULL) continue;
        s.push({t, state+1});
        if(state == 0) s.push({t->left, 0});
        else if(state == 1) {
            if(prev) prev->right = t;
            t->left = prev;
            prev = t;
            if(flag) {
                head = t;
                flag = false;
            }
        }
        else if(state == 2) s.push({t->right, 0});
    }
    return head;
}


输出:

25 12 30 10 36 15

请注意,不推荐使用上述静态变量(为简单起见,我们使用了静态变量)。想象一下为两棵或多棵树调用相同的函数的情况。 prev的旧值将在下一次调用不同的树时使用。为避免此类问题,我们可以使用双指针或指针引用。
时间复杂度:上述程序进行了简单的中序遍历,因此时间复杂度为 O(n),其中 n 是给定二叉树中的节点数。

下面的代码是上述中序遍历方法的直观迭代实现(灵感来自这个视频)——

C++

Node * bToDLL(Node *root)
{
    stack> s;
    s.push({root, 0});
    vector res;
    bool flag = true;
    Node* head = NULL;
    Node* prev = NULL;
    while(!s.empty()) {
        auto x = s.top();
        Node* t = x.first;
        int state = x.second;
        s.pop();
        if(state == 3 or t == NULL) continue;
        s.push({t, state+1});
        if(state == 0) s.push({t->left, 0});
        else if(state == 1) {
            if(prev) prev->right = t;
            t->left = prev;
            prev = t;
            if(flag) {
                head = t;
                flag = false;
            }
        }
        else if(state == 2) s.push({t->right, 0});
    }
    return head;
}

时间复杂度:O(N)

空间复杂度:O(N)