📜  使用线程二叉树的反向莫里斯遍历

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

使用线程二叉树的反向莫里斯遍历

给定一棵二叉树,任务是使用 Morris Traversal 进行反向中序遍历。

TBT

先决条件:
莫里斯遍历
线程二叉树

在具有n 个节点的二叉树中,有n + 1 个NULL 指针会浪费内存。因此,线程二叉树利用这些 NULL 指针来节省大量内存。
因此,在线程二叉树中,这些 NULL 指针将存储一些有用的信息。

1) 仅将前驱信息存储在 NULL 左指针中,称为左线程二叉树。
2) 仅在 NULL 右指针中存储后继信息,称为右线程二叉树。
3) 将前任信息存储在 NULL 左指针中,将后继信息存储在 NULL 右指针中,称为全线程二叉树或简称为线程二叉树。

莫里斯遍历可用于执行中序遍历、反向中序遍历、前序遍历,并且消耗恒定的额外内存 O(1)。

Reverse Morris Traversal :就是 Morris Traversal 的逆向形式。在反向 Morris 遍历中,首先创建指向当前节点的中序后继节点的链接,并使用这些链接打印数据,最后还原更改以恢复原始树,这将给出逆序遍历。

算法 :

1) Initialize Current as root.

2) While current is not NULL :

  2.1) If current has no right child
   a) Visit the current node.
   b) Move to the left child of current.

  2.2) Else, here we have 2 cases:
   a) Find the inorder successor of current node. 
      Inorder successor is the left most node 
      in the right subtree or right child itself.
   b) If the left child of the inorder successor is NULL:
      1) Set current as the left child of its inorder successor.
      2) Move current node to its right.
   c) Else, if the threaded link between the current node 
      and it's inorder successor already exists :
      1) Set left pointer of the inorder successor as NULL.
      2) Visit Current node.
      3) Move current to it's left child.
C++
// CPP code for reverse Morris Traversal
#include
 
using namespace std;
 
// Node structure
struct Node {
    int data;
    Node *left, *right;
};
 
// helper function to create a new node
Node *newNode(int data){
    Node *temp = new Node;
     
    temp->data = data;
    temp->right = temp->left = NULL;
 
    return temp;
}
 
// function for reverse inorder traversal
void MorrisReverseInorder(Node *root)
{
     
    if(!root)
        return ;
     
    // Auxiliary node pointers
    Node *curr, *successor;
     
    // initialize current as root
    curr = root;
     
    while(curr)
    {
        // case-1, if curr has no right child then
        // visit current and move to left child
        if(curr -> right == NULL)
        {
            cout << curr->data << " ";
            curr = curr->left;
        }
         
        // case-2
        else
        {
            // find the inorder successor of
            // current node i.e left most node in
            // right subtree or right child itself
            successor = curr->right;
             
            // finding left most in right subtree
            while(successor->left != NULL &&
                  successor->left != curr)
                    successor = successor->left;
                 
            // if the left of inorder successor is NULL
            if(successor->left == NULL)
            {
                // then connect left link to current node
                successor->left = curr;
                 
                // move current to right child
                curr = curr->right;
            }
             
            // otherwise inorder successor's left is
            // not NULL and already left is linked
            // with current node
            else
            {
                successor->left = NULL;
                 
                // visiting the current node
                cout << curr->data << " ";
 
                // move current to its left child
                curr = curr->left;
            }
        }
    }
}
 
// Driver code
int main()
{
 
/* Constructed binary tree is
          1
        /   \
       2     3
     /  \   /  \
    4    5  6    7
*/
 
Node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);
 
//reverse inorder traversal.
MorrisReverseInorder(root);
 
return 0;
}


Java
// Java code for reverse Morris Traversal
class GFG
{
 
// Node structure
static class Node
{
    int data;
    Node left, right;
};
 
// helper function to create a new node
static Node newNode(int data)
{
    Node temp = new Node();
     
    temp.data = data;
    temp.right = temp.left = null;
 
    return temp;
}
 
// function for reverse inorder traversal
static void MorrisReverseInorder(Node root)
{
     
    if(root == null)
        return ;
     
    // Auxiliary node pointers
    Node curr, successor;
     
    // initialize current as root
    curr = root;
     
    while(curr != null)
    {
        // case-1, if curr has no right child then
        // visit current and move to left child
        if(curr . right == null)
        {
                System.out.print( curr.data + " ");
            curr = curr.left;
        }
         
        // case-2
        else
        {
            // find the inorder successor of
            // current node i.e left most node in
            // right subtree or right child itself
            successor = curr.right;
             
            // finding left most in right subtree
            while(successor.left != null &&
                successor.left != curr)
                    successor = successor.left;
                 
            // if the left of inorder successor is null
            if(successor.left == null)
            {
                // then connect left link to current node
                successor.left = curr;
                 
                // move current to right child
                curr = curr.right;
            }
             
            // otherwise inorder successor's left is
            // not null and already left is linked
            // with current node
            else
            {
                successor.left = null;
                 
                // visiting the current node
                System.out.print( curr.data + " ");
 
                // move current to its left child
                curr = curr.left;
            }
        }
    }
}
 
// Driver code
public static void main(String args[])
{
 
/* Constructed binary tree is
        1
        / \
    2     3
    / \ / \
    4 5 6 7
*/
 
Node root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.left = newNode(4);
root.left.right = newNode(5);
root.right.left = newNode(6);
root.right.right = newNode(7);
 
// reverse inorder traversal.
MorrisReverseInorder(root);
}
}
 
// This code is contributed by Arnab Kundu


Python3
# Python3 for reverse Morris Traversal
 
# Utility function to create a new
# tree node
class newNode:
    def __init__(self,data):
        self.data = data
        self.left = self.right = None
 
# function for reverse inorder traversal
def MorrisReverseInorder(root):
 
    if( not root) :
        return
         
    # initialize current as root
    curr = root
    successor = 0
     
    while(curr):
     
        # case-1, if curr has no right child then
        # visit current and move to left child
        if(curr.right == None) :
         
            print(curr.data, end = " ")
            curr = curr.left
         
        # case-2
        else:
         
            # find the inorder successor of
            # current node i.e left most node in
            # right subtree or right child itself
            successor = curr.right
             
            # finding left most in right subtree
            while(successor.left != None and
                  successor.left != curr):
                successor = successor.left
                 
            # if the left of inorder successor is None
            if(successor.left == None) :
             
                # then connect left link to current node
                successor.left = curr
                 
                # move current to right child
                curr = curr.right
             
            # otherwise inorder successor's left is
            # not None and already left is linked
            # with current node
            else:
             
                successor.left = None
                 
                # visiting the current node
                print(curr.data, end = " " )
 
                # move current to its left child
                curr = curr.left
 
# Driver code
if __name__ =="__main__":
    """ Constructed binary tree is
        1
        / \
    2     3
    / \ / \
    4 5 6 7
"""
 
    root = newNode(1)
    root.left = newNode(2)
    root.right = newNode(3)
    root.left.left = newNode(4)
    root.left.right = newNode(5)
    root.right.left = newNode(6)
    root.right.right = newNode(7)
 
    #reverse inorder traversal.
    MorrisReverseInorder(root)
 
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)


C#
// C# code for reverse Morris Traversal
using System;
 
class GFG
{
 
// Node structure
public class Node
{
    public int data;
    public Node left, right;
};
 
// helper function to create a new node
static Node newNode(int data)
{
    Node temp = new Node();
     
    temp.data = data;
    temp.right = temp.left = null;
 
    return temp;
}
 
// function for reverse inorder traversal
static void MorrisReverseInorder(Node root)
{
     
    if(root == null)
        return ;
     
    // Auxiliary node pointers
    Node curr, successor;
     
    // initialize current as root
    curr = root;
     
    while(curr != null)
    {
        // case-1, if curr has no right child then
        // visit current and move to left child
        if(curr . right == null)
        {
                Console.Write( curr.data + " ");
            curr = curr.left;
        }
         
        // case-2
        else
        {
            // find the inorder successor of
            // current node i.e left most node in
            // right subtree or right child itself
            successor = curr.right;
             
            // finding left most in right subtree
            while(successor.left != null &&
                successor.left != curr)
                    successor = successor.left;
                 
            // if the left of inorder successor is null
            if(successor.left == null)
            {
                // then connect left link to current node
                successor.left = curr;
                 
                // move current to right child
                curr = curr.right;
            }
             
            // otherwise inorder successor's left is
            // not null and already left is linked
            // with current node
            else
            {
                successor.left = null;
                 
                // visiting the current node
                Console.Write( curr.data + " ");
 
                // move current to its left child
                curr = curr.left;
            }
        }
    }
}
 
// Driver code
public static void Main(String []args)
{
 
/* Constructed binary tree is
        1
        / \
    2 3
    / \ / \
    4 5 6 7
*/
 
Node root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.left = newNode(4);
root.left.right = newNode(5);
root.right.left = newNode(6);
root.right.right = newNode(7);
 
// reverse inorder traversal.
MorrisReverseInorder(root);
}
}
 
// This code contributed by Rajput-Ji


Javascript


输出:
7 3 6 1 5 2 4

时间复杂度: O(n)
辅助空间: O(1)