📜  将二叉树展平为链接列表

📅  最后修改于: 2021-04-23 07:01:53             🧑  作者: Mango

给定一棵二叉树,将其平整化为就地链表。不允许使用辅助数据结构。展平后,每个节点的左侧应指向NULL,右侧应包含按顺序排列的下一个节点。

例子:

Input : 
          1
        /   \
       2     5
      / \     \
     3   4     6

Output :
    1
     \
      2
       \
        3
         \
          4
           \
            5
             \
              6

Input :
        1
       / \
      3   4
         /
        2
         \
          5
Output :
     1
      \
       3
        \
         4
          \
           2
            \ 
             5

简单方法:一个简单的解决方案是通过“队列”使用“级别顺序遍历”。在级别顺序遍历中,跟踪先前的节点。将当前节点作为上一个节点的右子节点,将上一个节点的左节点作为NULL。该解决方案需要队列,但问题要求解决而无需其他数据结构。

无需附加数据结构即可高效地在左子树中递归查找没有孙子代且左子代和右子代都没有的节点。然后将node-> right存储在临时目录中,并使node-> right = node-> left。通过node = node-> right在节点右边的第一个节点NULL中插入temp。重复直到将其转换为链接列表。

例如,

展平二叉树示例

C++
/* C++ Program to flatten a given Binary
   Tree into linked list */
#include 
using namespace std;
 
struct Node {
    int key;
    Node *left, *right;
};
 
/* utility that allocates a new Node
   with the given key  */
Node* newNode(int key)
{
    Node* node = new Node;
    node->key = key;
    node->left = node->right = NULL;
    return (node);
}
 
// Function to convert binary tree into
// linked list by altering the right node
// and making left node point to NULL
void flatten(struct Node* root)
{
    // base condition- return if root is NULL
    // or if it is a leaf node
    if (root == NULL || root->left == NULL &&
                        root->right == NULL) {
        return;
    }
 
    // if root->left exists then we have
    // to make it root->right
    if (root->left != NULL) {
 
        // move left recursively
        flatten(root->left);
    
        // store the node root->right
        struct Node* tmpRight = root->right;
        root->right = root->left;
        root->left = NULL;
 
        // find the position to insert
        // the stored value  
        struct Node* t = root->right;
        while (t->right != NULL) {
            t = t->right;
        }
 
        // insert the stored value
        t->right = tmpRight;
    }
 
    // now call the same function
    // for root->right
    flatten(root->right);
}
 
// To find the inorder traversal
void inorder(struct Node* root)
{
    // base condition
    if (root == NULL)
        return;
    inorder(root->left);
    cout << root->key << " ";
    inorder(root->right);
}
 
/* Driver program to test above functions*/
int main()
{
    /*    1
        /   \
       2     5
      / \     \
     3   4     6 */
    Node* root = newNode(1);
    root->left = newNode(2);
    root->right = newNode(5);
    root->left->left = newNode(3);
    root->left->right = newNode(4);
    root->right->right = newNode(6);
 
    flatten(root);
 
    cout << "The Inorder traversal after "
            "flattening binary tree ";
    inorder(root);
    return 0;
}


Java
// Java program to flatten a given
// Binary Tree into linked list
 
// A binary tree node
class Node
{
    int data;
    Node left, right;
 
    Node(int key)
    {
        data = key;
        left = right = null;
    }
}
 
class BinaryTree{
     
Node root;
 
// Function to convert binary tree into
// linked list by altering the right node
// and making left node NULL
public void flatten(Node node)
{
     
    // Base case - return if root is NULL
    if (node == null)
        return;
 
    // Or if it is a leaf node
    if (node.left == null &&
       node.right == null)
        return;
 
    // If root.left children exists then we have
    // to make it node.right (where node is root)
    if (node.left != null)
    {
         
        // Move left recursively
        flatten(node.left);
 
        // Store the node.right in
        // Node named tempNode
        Node tempNode = node.right;
        node.right = node.left;
        node.left = null;
 
        // Find the position to insert
        // the stored value
        Node curr = node.right;
        while (curr.right != null)
        {
            curr = curr.right;
        }
 
        // Insert the stored value
        curr.right = tempNode;
    }
 
    // Now call the same function
    // for node.right
    flatten(node.right);
 
}
 
// Function for Inorder traversal
public void inOrder(Node node)
{
     
    // Base Condition
    if (node == null)
        return;
 
    inOrder(node.left);
    System.out.print(node.data + " ");
    inOrder(node.right);
}
 
// Driver code
public static void main(String[] args)
{
    BinaryTree tree = new BinaryTree();
 
    /*    1
        /   \
       2     5
      / \     \
     3   4     6 */
 
    tree.root = new Node(1);
    tree.root.left = new Node(2);
    tree.root.right = new Node(5);
    tree.root.left.left = new Node(3);
    tree.root.left.right = new Node(4);
    tree.root.right.right = new Node(6);
 
    System.out.println("The Inorder traversal after " +
                       "flattening binary tree ");
                        
    tree.flatten(tree.root);
    tree.inOrder(tree.root);
}
}
 
// This code is contributed by Yash Singhal


Python3
# Python3 program to flatten a given Binary
# Tree into linked list
class Node:
     
    def __init__(self):
         
        self.key = 0
        self.left = None
        self.right = None
 
# Utility that allocates a new Node
# with the given key
def newNode(key):
     
    node = Node()
    node.key = key
    node.left = node.right = None
    return (node)
 
# Function to convert binary tree into
# linked list by altering the right node
# and making left node point to None
def flatten(root):
 
    # Base condition- return if root is None
    # or if it is a leaf node
    if (root == None or root.left == None and
                        root.right == None):
        return
     
    # If root.left exists then we have
    # to make it root.right
    if (root.left != None):
 
        # Move left recursively
        flatten(root.left)
    
        # Store the node root.right
        tmpRight = root.right
        root.right = root.left
        root.left = None
 
        # Find the position to insert
        # the stored value  
        t = root.right
        while (t.right != None):
            t = t.right
 
        # Insert the stored value
        t.right = tmpRight
 
    # Now call the same function
    # for root.right
    flatten(root.right)
 
# To find the inorder traversal
def inorder(root):
 
    # Base condition
    if (root == None):
        return
     
    inorder(root.left)
    print(root.key, end = ' ')
    inorder(root.right)
 
# Driver Code
if __name__=='__main__':
     
    '''   1
        /   \
       2     5
      / \     \
     3   4     6 '''
    root = newNode(1)
    root.left = newNode(2)
    root.right = newNode(5)
    root.left.left = newNode(3)
    root.left.right = newNode(4)
    root.right.right = newNode(6)
 
    flatten(root)
 
    print("The Inorder traversal after "
          "flattening binary tree ",
          end = '')
    inorder(root)
 
# This code is contributed by pratham76


C#
// C# program to flatten a given
// Binary Tree into linked list
using System;
 
// A binary tree node
class Node
{
  public int data;
  public Node left, right;
 
  public Node(int key)
  {
    data = key;
    left = right = null;
  }
}
 
class BinaryTree
{   
  Node root;
 
  // Function to convert binary tree into
  // linked list by altering the right node
  // and making left node NULL
  public void flatten(Node node)
  {
 
    // Base case - return if root is NULL
    if (node == null)
      return;
 
    // Or if it is a leaf node
    if (node.left == null &&
        node.right == null)
      return;
 
    // If root.left children exists then we have
    // to make it node.right (where node is root)
    if (node.left != null)
    {
 
      // Move left recursively
      flatten(node.left);
 
      // Store the node.right in
      // Node named tempNode
      Node tempNode = node.right;
      node.right = node.left;
      node.left = null;
 
      // Find the position to insert
      // the stored value
      Node curr = node.right;
      while (curr.right != null)
      {
        curr = curr.right;
      }
 
      // Insert the stored value
      curr.right = tempNode;
    }
 
    // Now call the same function
    // for node.right
    flatten(node.right);
 
  }
 
  // Function for Inorder traversal
  public void inOrder(Node node)
  {
 
    // Base Condition
    if (node == null)
      return;
    inOrder(node.left);
    Console.Write(node.data + " ");
    inOrder(node.right);
  }
 
  // Driver code
  public static void Main(string[] args)
  {
    BinaryTree tree = new BinaryTree();
 
    /* 1
        / \
    2     5
    / \     \
    3 4     6 */
 
    tree.root = new Node(1);
    tree.root.left = new Node(2);
    tree.root.right = new Node(5);
    tree.root.left.left = new Node(3);
    tree.root.left.right = new Node(4);
    tree.root.right.right = new Node(6);
    Console.Write("The Inorder traversal after " +
                  "flattening binary tree ");                       
    tree.flatten(tree.root);
    tree.inOrder(tree.root);
  }
}
 
// This code is contributed by rutvik_56


输出:
The Inorder traversal after flattening 
binary tree 1 2 3 4 5 6