Get last node of the binary tree following given pattern starting from X

Given a binary tree, target node X and a string patt. The task is to find the last node of the binary tree following the pattern starting from X. Pattern may contain only five types of character ‘p’, ‘l’, ‘r’, ‘m’ and ‘n’. For any character encountered:

  • p: Get to the parent of the current node.
  • l: Get to the left child of the current node.
  • r: Get to the right child of the current node.
  • m: Get to the left sibling in the same level.
  • n: Get to the right sibling in the same level.

Note that if the node doesn’t exist corresponding to any character then skip that character and remain on the current node.

Examples:

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

Approach:

  1. Create an auxiliary tree from the original tree but include three extra pointers (parent pointer, left and right sibling pointers).
    • Parent pointer will point to the parent of the current node.
    • Left pointer will point to the left sibling.
    • Right pointer will point to the right sibling.
  2. Check the image below:
  3. After creation of this tree, we can easily traverse the given pattern.
  4. If any node doesn’t exist corresponding any character then simply skip that character.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
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<auxNode*> 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;
}

chevron_right


Output:

22


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.