📜  按照从 X 开始的给定模式获取二叉树的最后一个节点

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

按照从 X 开始的给定模式获取二叉树的最后一个节点

给定二叉树、目标节点X和字符串patt 。任务是按照从X开始的模式找到二叉树的最后一个节点。模式只能包含五种类型的字符'p''l''r''m''n' 。对于遇到的任何字符:

  • p:获取当前节点的父节点。
  • l:获取当前节点的左孩子。
  • r:获取当前节点的右孩子。
  • m:到同级的左兄弟。
  • n:在同一关卡中找到正确的兄弟姐妹。

请注意,如果节点不存在对应于任何字符,则跳过该字符并保留在当前节点上。

例子:

Input:
         10 
        /   \ 
      12    13 
           /   \ 
         14     15 
        /  \    /  \ 
       21  22  23  24 

X = 14, patt = "npmrprrlm"
Output: 22
Starting from the target node 14
n: 14 -> 15
p: 15 -> 13
m: 13 -> 12
r: 12 -> 12 (there is no right child)
p: 12 -> 10
r: 10 -> 13
r: 13 -> 15
l: 15 -> 23
m: 23 -> 22

Input:
         5
        /  \ 
      16    8

X = 16, patt = "pppp"
Output: 5

方法:

  1. 从原始树创建一个辅助树,但包括三个额外的指针(父指针、左右兄弟指针)。
    • 父指针将指向当前节点的父节点。
    • 左指针将指向左兄弟。
    • 右指针将指向右兄弟。
  2. 检查上图:
  3. 创建这棵树后,我们可以轻松地遍历给定的模式。
  4. 如果任何节点不存在对应于任何字符,则只需跳过该字符。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// A Tree node
struct Node 
{
    int key;
    struct Node *left, *right;
};
  
// Utility function to create a new node
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->key = key;
    temp->left = temp->right = NULL;
    return (temp);
}
  
struct auxNode 
{
    int key;
    auxNode *left, *right, *parent;
  
    // Pointer will point the left node
    // at the same level in the tree
    auxNode* llNode;
  
    // Pointer will point the right node
    // at the same level in the tree
    auxNode* rlNode;
};
  
auxNode* newAuxNode(int key)
{
    auxNode* temp = new auxNode;
    temp->key = key;
    temp->left = temp->right = temp->parent
        = temp->llNode = temp->rlNode = NULL;
    return temp;
}
  
// Function to create the auxiliary tree
auxNode* createAuxTree(Node* root)
{
    if (root == NULL)
        return NULL;
    auxNode* auxTree = newAuxNode(root->key);
  
    auxTree->left = createAuxTree(root->left);
    auxTree->right = createAuxTree(root->right);
    return auxTree;
}
  
// Function for arranging the parent node for every node
void makeParentNodePoint(auxNode* auxTree, 
                         auxNode* prev_ptr)
{
    if (auxTree == NULL)
        return;
  
    // Set the parent
    if (prev_ptr != NULL) 
    {
        auxTree->parent = prev_ptr;
    }
  
    // Recur for left and right sub-trees
    makeParentNodePoint(auxTree->left, auxTree);
    makeParentNodePoint(auxTree->right, auxTree);
}
  
// Function for arranging the left and right
// node for every node at the same level
void makeSameLevelNodePoint(auxNode* auxTree)
{
    queue qu;
    qu.push(auxTree);
    while (!qu.empty())
    {
        int qsize = qu.size();
        while (qsize--) 
        {
            auxNode* top_ele;
            top_ele = qu.front();
            qu.pop();
            if (qsize)
            {
                top_ele->rlNode = qu.front();
                qu.front()->llNode = top_ele;
            }
            if (top_ele->left != NULL)
            {
                qu.push(top_ele->left);
            }
            if (top_ele->right != NULL) 
            {
                qu.push(top_ele->right);
            }
        }
    }
}
  
// Function to return the target node address
auxNode* getTargetNodeAddress(auxNode* auxTree, int tNode)
{
    if (auxTree == NULL)
        return NULL;
  
    if (auxTree->key == tNode)
    {
        return auxTree;
    }
    auxNode* is_null = getTargetNodeAddress(auxTree->left, tNode);
    if (is_null != NULL)
        return is_null;
    return getTargetNodeAddress(auxTree->right, tNode);
}
  
// Utility function to print the last node
void printNode(auxNode* auxTree, 
               auxNode* target_node, 
               string pattern)
{
  
    // Perform the movement
    for (int i = 0; i < pattern.length(); i++) 
    {
        switch (pattern[i])
        {
  
        // Get to the parent
        case 'p':
        case 'P':
            if (target_node->parent != NULL)
            {
                target_node = target_node->parent;
            }
            break;
  
        // Get to the left child
        case 'l':
        case 'L':
            if (target_node->left != NULL) 
            {
                target_node = target_node->left;
            }
            break;
  
        // Get to the right child
        case 'r':
        case 'R':
            if (target_node->right != NULL)
                target_node = target_node->right;
            break;
  
        // Get to the left sibling in the same level
        case 'm':
        case 'M':
            if (target_node->llNode != NULL)
                target_node = target_node->llNode;
            break;
  
        // Get to the right sibling in the same level
        case 'n':
        case 'N':
            if (target_node->rlNode != NULL)
                target_node = target_node->rlNode;
            break;
        default:
            return;
        }
    }
    cout << target_node->key;
}
  
// Function to print the last node 
// according to the pattern
void printNodeUsingPattern(Node* root, 
                           string pattern, int tNode)
{
    // Function will create auxiliary tree same as
    // original tree with left child and right child
    auxNode* auxTree = createAuxTree(root);
  
    // Function will make every node 
    // point to its parent node
    makeParentNodePoint(auxTree, NULL);
  
    // Function will make every node point to its
    // left and right node at the same level
    makeSameLevelNodePoint(auxTree);
  
    // Function will give the address of the target node
    auxNode* target_node = getTargetNodeAddress(auxTree, tNode);
  
    // If target node found
    if (target_node != NULL)
    {
  
        // Function call to print the last node
        // according to the given pattern
        printNode(auxTree, target_node, pattern);
    }
    else
        cout << "-1"; 
} 
    
// Driver code 
int main() 
{ 
    Node* root = newNode(10); 
    root->left = newNode(12); 
    root->right = newNode(13); 
    root->right->left = newNode(14); 
    root->right->right = newNode(15); 
    root->right->left->left = newNode(21); 
    root->right->left->right = newNode(22); 
    root->right->right->left = newNode(23); 
    root->right->right->right = newNode(24); 
    int target_node = 14; 
    string str = "npmrprrlm"; 
    printNodeUsingPattern(root, str, target_node); 
    
    return 0; 
}


Python3
# Python3 implementation of the approach
import queue
  
# A Tree node
class Node: 
    def __init__(self,key): 
        self.left = None
        self.right = None
        self.key = key
          
class auxNode:
    def __init__(self,key):
        self.left = None
        self.right = None
        self.key = key
        self.parent = None
  
        # Pointer will point the left node
        # at the same level in the tree
        self.llNode = None
  
        # Pointer will point the right node
        # at the same level in the tree
        self.rlNode = None
      
def newAuxNode(key):
  
    temp = auxNode(key)
    return temp
  
def createAuxTree(root):
  
    if (root == None) :
        return None
      
    auxTree = auxNode(root.key)
      
    auxTree.left = createAuxTree(root.left)
    auxTree.right = createAuxTree(root.right)
    return auxTree
      
# Function for arranging the 
# parent node for every node
def makeParentNodePoint(auxTree, prev_ptr):
  
    if (auxTree == None):
        return;
  
    # Set the parent
    if (prev_ptr != None) :
        auxTree.parent = prev_ptr
        #print("Parent : ",auxTree.parent.key)
      
    # Recur for left and right sub-trees
    makeParentNodePoint(auxTree.left, auxTree)
    makeParentNodePoint(auxTree.right, auxTree)
      
# Function for arranging the left and right
# node for every node at the same level
def makeSameLevelNodePoint(auxTree):
  
    qu = queue.Queue(maxsize = 50)
    qu.put(auxTree)
    while (not qu.empty()) :
        size = qu.qsize()
        while (size) :
            size -= 1
              
            top_ele = qu.get();
              
            if (size) :
                front = qu.get()
                top_ele.rlNode = front
                front.llNode = top_ele
                  
                # since we don't have peek function 
                # in python creating 2nd queue 
                # to store elements below peek element
                qu2 = queue.Queue(maxsize = 50)
                while not qu.empty():
                    a = qu.get()
                    qu2.put(a)
                      
                # putting back front element 
                # in queue 1 all elements which 
                # were behind it in original queue
                qu.put(front)
                while not qu2.empty():
                    qu.put(qu2.get())
              
            if (top_ele.left != None) :
                qu.put(top_ele.left)
              
            if (top_ele.right != None) :
                qu.put(top_ele.right)
                  
# Function to return the target node address
def getTargetNodeAddress(auxTree, tNode):
  
    if (auxTree == None):
        return None
  
    if (auxTree.key == tNode) :
        return auxTree
      
    is_null = getTargetNodeAddress(auxTree.left, tNode)
    if (is_null != None):
        return is_null
    return getTargetNodeAddress(auxTree.right, tNode)
      
# Utility function to print the last node
def printNode(auxTree, target_node, pattern):
  
    # Perform the movement
    for i in range(len(pattern)) :
          
        # Get to the parent
        if pattern[i] == 'p' or pattern[i] == 'P':
      
            if (target_node.parent != None): 
                target_node = target_node.parent
          
        # Get to the left child
        elif pattern[i] == 'l' or pattern[i] == 'L':
            if (target_node.left != None) :
                target_node = target_node.left
              
        # Get to the right child
        elif pattern[i] == 'r' or pattern[i] == 'R':
            if (target_node.right != None):
                target_node = target_node.right
              
        # Get to the left sibling in the same level
        elif pattern[i] == 'm' or pattern[i] == 'M':
            if (target_node.llNode != None):
                target_node = target_node.llNode
          
        # Get to the right sibling in the same level
        elif pattern[i] == 'n' or pattern[i] == 'N':
            if (target_node.rlNode != None):
                target_node = target_node.rlNode
        else:
            return
  
    print(target_node.key, end = ' ')
  
# Function to print the last node 
# according to the pattern
def printNodeUsingPattern(root, pattern, tNode):
      
    # Function will create auxiliary tree same as
    # original tree with left child and right child
    auxTree = createAuxTree(root)
  
    # Function will make every node
    # point to its parent node
    makeParentNodePoint(auxTree, None)
      
    # Function will make every node point to its
    # left and right node at the same level
    makeSameLevelNodePoint(auxTree)
      
    # Function will give the address of the target node
    target_node = getTargetNodeAddress(auxTree, tNode)
  
    # If target node found
    if (target_node != None) :
  
        # Function call to print the last node
        # according to the given pattern
        printNode(auxTree, target_node, pattern);
  
    else :
        print("-1")
  
# Driver Code
root = Node(10) 
root.left = Node(12)
root.right = Node(13)
root.right.left = Node(14)
root.right.right = Node(15)
root.right.left.left = Node(21)
root.right.left.right = Node(22)
root.right.right.left = Node(23)
root.right.right.right = Node(24)
target_node = 14
string = "npmrprrlm"
  
printNodeUsingPattern(root, string, target_node)
  
# This code is contributed by Sadik Ali


Javascript


输出:
22