📌  相关文章
📜  二叉树中任意两个节点之间的打印路径套装2

📅  最后修改于: 2021-04-22 03:20:25             🧑  作者: Mango

给定一个由不同节点和一对节点组成的二叉树。任务是在二叉树中找到并打印两个给定节点之间的路径。
例子:

方法:本文讨论了一种解决此问题的方法。在本文中,将讨论甚至优化的递归方法。
在这种递归方法中,以下是步骤:

  1. 递归查找第一个值,找到后将其添加到堆栈中。
  2. 现在,无论是在回溯还是正向跟踪中访问的每个节点,都将值添加到堆栈中,但是如果在正向跟踪中添加了该节点,则在回溯中将其删除,并继续进行此操作,直到找到第二个值或所有节点都被访问为止。

例如:考虑在上面的树中找到7到9之间的路径。我们将树作为DFS遍历,一旦找到值7,就将其添加到堆栈中。遍历路径0-> 1-> 3-> 7。
现在,在回溯的同时,将3和1添加到堆栈中。因此,到目前为止,堆栈具有[7,3,1],子级1具有正确的子级,因此我们首先将其添加到堆栈中。现在,堆栈包含[7、3、1、4]。访问4的左孩子,将其添加到堆栈中。堆栈现在包含[7、3、1、4、8]。由于没有其他节点,我们将返回到上一个节点,并且由于已经将8添加到堆栈中,因此将其删除。现在节点4有一个合适的子节点,我们将其添加到堆栈中,因为这是我们一直在寻找的第二个值,因此不会再进行任何递归调用。最后,堆栈包含[7、3、1、4、9]。
下面是上述方法的实现:

C++
// CPP implementation of the approach
#include 
using namespace std;
 
// A binary tree node
class Node {
 public:
  int value;
  Node *left, *right;
 
  Node(int value) {
    this->value = value;
    left = NULL;
    right = NULL;
  }
};
 
bool firstValueFound = false;
bool secondValueFound = false;
stack stk;
Node *root = NULL;
 
// Function to find the path between
// two nodes in binary tree
void pathBetweenNode(Node *root, int v1, int v2) {
  // Base condition
  if (root == NULL) return;
 
  // If both the values are found then return
  if (firstValueFound && secondValueFound) return;
 
  // Starting the stack frame with
  // isAddedToStack = false flag
  bool isAddedToStack = false;
 
  // If one of the value is found then add the
  // value to the stack and make the isAddedToStack = true
  if (firstValueFound ^ secondValueFound) {
    stk.push(root);
    isAddedToStack = true;
  }
 
  // If none of the two values is found
  if (!(firstValueFound && secondValueFound)) {
    pathBetweenNode(root->left, v1, v2);
  }
 
  // Ccopy of current state of firstValueFound
  // and secondValueFound flag
  bool localFirstValueFound = firstValueFound;
  bool localSecondValueFound = secondValueFound;
 
  // If the first value is found
  if (root->value == v1) firstValueFound = true;
 
  // If the second value is found
  if (root->value == v2) secondValueFound = true;
 
  bool localAdded = false;
 
  // If one of the value is found and the value
  // was not added to the stack yet or there was
  // only one value found and now both the values
  // are found and was not added to
  // the stack then add it
  if (((firstValueFound ^ secondValueFound) ||
       ((localFirstValueFound ^ localSecondValueFound) &&
        (firstValueFound && secondValueFound))) &&
      !isAddedToStack) {
    localAdded = true;
    stk.push(root);
  }
 
  // If none of the two values is found yet
  if (!(firstValueFound && secondValueFound)) {
    pathBetweenNode(root->right, v1, v2);
  }
 
  if ((firstValueFound ^ secondValueFound) && !isAddedToStack && !localAdded)
    stk.push(root);
 
  if ((firstValueFound ^ secondValueFound) && isAddedToStack) stk.pop();
}
 
// Function to find the path between
// two nodes in binary tree
stack pathBetweenNode(int v1, int v2)
{
   
  // Global root
  pathBetweenNode(::root, v1, v2);
 
  // If both the values are found
  // then return the stack
  if (firstValueFound && secondValueFound)
  {
     
    // Global Stack Object
    return ::stk;
  }
 
  // If none of the two values is
  // found then return empty stack
  stack stk;
  return stk;
}
 
// Recursive function to print the
// contents of a stack in reverse
void print(stack stk)
{
   
  // If the stack is empty
  if (stk.empty()) return;
 
  // Get the top value
  int value = stk.top()->value;
  stk.pop();
 
  // Recursive call
  print(stk);
 
  // Print the popped value
  cout << value << " ";
}
 
// Driver code
int main(int argc, char const *argv[])
{
  root = new Node(0);
  root->left = new Node(1);
  root->right = new Node(2);
  root->left->left = new Node(3);
  root->left->right = new Node(4);
  root->right->left = new Node(5);
  root->right->right = new Node(6);
  root->left->left->left = new Node(7);
  root->left->right->left = new Node(8);
  root->left->right->right = new Node(9);
 
  // Find and print the path
  stack stck = pathBetweenNode(7, 4);
  print(stck);
}
 
// This code is contributed by sanjeev2552


Java
// Java implementation of the approach
import java.util.Stack;
 
public class GFG {
 
    // A binary tree node
    private static class Node {
        public Node left;
        public int value;
        public Node right;
 
        public Node(int value)
        {
            this.value = value;
            left = null;
            right = null;
        }
    }
 
    private boolean firstValueFound = false;
    private boolean secondValueFound = false;
    private Stack stack = new Stack();
    private Node root = null;
 
    public GFG(Node root)
    {
        this.root = root;
    }
 
    // Function to find the path between
    // two nodes in binary tree
    public Stack pathBetweenNode(int v1, int v2)
    {
        pathBetweenNode(this.root, v1, v2);
 
        // If both the values are found
        // then return the stack
        if (firstValueFound && secondValueFound) {
            return stack;
        }
 
        // If none of the two values is
        // found then return empty stack
        return new Stack();
    }
 
    // Function to find the path between
    // two nodes in binary tree
    private void pathBetweenNode(Node root, int v1, int v2)
    {
        // Base condition
        if (root == null)
            return;
 
        // If both the values are found then return
        if (firstValueFound && secondValueFound)
            return;
 
        // Starting the stack frame with
        // isAddedToStack = false flag
        boolean isAddedToStack = false;
 
        // If one of the value is found then add the
        // value to the stack and make the isAddedToStack = true
        if (firstValueFound ^ secondValueFound) {
            stack.add(root);
            isAddedToStack = true;
        }
 
        // If none of the two values is found
        if (!(firstValueFound && secondValueFound)) {
            pathBetweenNode(root.left, v1, v2);
        }
 
        // Ccopy of current state of firstValueFound
        // and secondValueFound flag
        boolean localFirstValueFound = firstValueFound;
        boolean localSecondValueFound = secondValueFound;
 
        // If the first value is found
        if (root.value == v1)
            firstValueFound = true;
 
        // If the second value is found
        if (root.value == v2)
            secondValueFound = true;
 
        boolean localAdded = false;
 
        // If one of the value is found and the value
        // was not added to the stack yet or there was
        // only one value found and now both the values
        // are found and was not added to
        // the stack then add it
        if (((firstValueFound ^ secondValueFound)
             || ((localFirstValueFound ^ localSecondValueFound)
                 && (firstValueFound && secondValueFound)))
            && !isAddedToStack) {
            localAdded = true;
            stack.add(root);
        }
 
        // If none of the two values is found yet
        if (!(firstValueFound && secondValueFound)) {
            pathBetweenNode(root.right, v1, v2);
        }
 
        if ((firstValueFound ^ secondValueFound)
            && !isAddedToStack && !localAdded)
            stack.add(root);
 
        if ((firstValueFound ^ secondValueFound)
            && isAddedToStack)
            stack.pop();
    }
 
    // Recursive function to print the
    // contents of a stack in reverse
    private static void print(Stack stack)
    {
 
        // If the stack is empty
        if (stack.isEmpty())
            return;
 
        // Get the top value
        int value = stack.pop().value;
 
        // Recursive call
        print(stack);
 
        // Print the popped value
        System.out.print(value + " ");
    }
 
    // Driver code
    public static void main(String[] args)
    {
        Node root = new Node(0);
        root.left = new Node(1);
        root.right = new Node(2);
        root.left.left = new Node(3);
        root.left.right = new Node(4);
        root.right.left = new Node(5);
        root.right.right = new Node(6);
        root.left.left.left = new Node(7);
        root.left.right.left = new Node(8);
        root.left.right.right = new Node(9);
 
        // Find and print the path
        GFG pathBetweenNodes = new GFG(root);
        Stack stack
            = pathBetweenNodes.pathBetweenNode(7, 4);
        print(stack);
    }
}


Python3
# Python3 implementation of
# the above approach
 
# A binary tree node
class Node:
 
    def __init__(self, value):
 
        self.left = None
        self.right = None
        self.value = value
 
firstValueFound = False
secondValueFound = False
stack = []
root = None
 
# Function to find the path
# between two nodes in binary
# tree
def pathBetweennode(v1, v2):
 
    global firstValueFound, secondValueFound
    pathBetweenNode(root, v1, v2)
 
    # If both the values are found
    # then return the stack
    if (firstValueFound and
        secondValueFound):
        return stack
 
    # If none of the two values is
    # found then return empty stack
    return []
 
# Function to find the path
# between two nodes in binary
# tree
def pathBetweenNode(root,
                    v1, v2):
    global firstValueFound, secondValueFound
     
    # Base condition
    if (root == None):
        return
 
    # If both the values are found
    # then return
    if (firstValueFound and
        secondValueFound):
        return
 
    # Starting the stack frame with
    # isAddedToStack = false flag
    isAddedToStack = False
 
    # If one of the value is found
    # then add the value to the
    # stack and make the isAddedToStack = true
    if (firstValueFound ^ secondValueFound):
        stack.append(root)
        isAddedToStack = True
 
    # If none of the two values
    # is found
    if (not (firstValueFound and
             secondValueFound)):
        pathBetweenNode(root.left,
                        v1, v2)
 
    # Ccopy of current state of
    # firstValueFound and
    # secondValueFound flag
    localFirstValueFound = firstValueFound
    localSecondValueFound = secondValueFound
 
    # If the first value is found
    if (root.value == v1):
        firstValueFound = True
 
    # If the second value is found
    if (root.value == v2):
        secondValueFound = True
 
    localAdded = False
 
    # If one of the value is found
    # and the value was not added
    # to the stack yet or there was
    # only one value found and now
    # both the values are found and
    # was not added to the stack
    # then add it
    if (((firstValueFound ^
          secondValueFound) or
        ((localFirstValueFound ^
          localSecondValueFound) and
         (firstValueFound and
          secondValueFound))) and
          not isAddedToStack):
        localAdded = True
        stack.append(root)
 
    # If none of the two values
    # is found yet
    if (not (firstValueFound and
             secondValueFound)):
        pathBetweenNode(root.right,
                        v1, v2)
 
    if ((firstValueFound ^
         secondValueFound) and
         not isAddedToStack and
         not localAdded):
        stack.append(root)
 
    if ((firstValueFound ^
         secondValueFound) and
         isAddedToStack):
        stack.pop()
 
# Recursive function to print
# the contents of a stack in
# reverse
def pri(stack):
 
    # If the stack is empty
    if (len(stack) == 0):
        return
 
    # Get the top value
    value = stack.pop().value
 
    # Recursive call
    pri(stack)
 
    # Print the popped value
    print(value, end = " ")
 
# Driver code
if __name__ == "__main__":
 
    root = Node(0)
    root.left = Node(1)
    root.right = Node(2)
    root.left.left = Node(3)
    root.left.right = Node(4)
    root.right.left = Node(5)
    root.right.right = Node(6)
    root.left.left.left = Node(7)
    root.left.right.left = Node(8)
    root.left.right.right = Node(9)
 
    # Find and print the path
    stack = pathBetweennode(7, 4)
    pri(stack)
 
# This code is contributed by Rutvik_56


C#
// C# implementation of the approach
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG
{
 
    // A binary tree node
    public class Node
    {
        public Node left;
        public int value;
        public Node right;
 
        public Node(int value)
        {
            this.value = value;
            left = null;
            right = null;
        }
    }
 
    private Boolean firstValueFound = false;
    private Boolean secondValueFound = false;
    private Stack stack = new Stack();
    private Node root = null;
 
    public GFG(Node root)
    {
        this.root = root;
    }
 
    // Function to find the path between
    // two nodes in binary tree
    public Stack pathBetweenNode(int v1, int v2)
    {
        pathBetweenNode(this.root, v1, v2);
 
        // If both the values are found
        // then return the stack
        if (firstValueFound && secondValueFound)
        {
            return stack;
        }
 
        // If none of the two values is
        // found then return empty stack
        return new Stack();
    }
 
    // Function to find the path between
    // two nodes in binary tree
    private void pathBetweenNode(Node root, int v1, int v2)
    {
        // Base condition
        if (root == null)
            return;
 
        // If both the values are found then return
        if (firstValueFound && secondValueFound)
            return;
 
        // Starting the stack frame with
        // isAddedToStack = false flag
        Boolean isAddedToStack = false;
 
        // If one of the value is found then add the
        // value to the stack and make the isAddedToStack = true
        if (firstValueFound ^ secondValueFound)
        {
            stack.Push(root);
            isAddedToStack = true;
        }
 
        // If none of the two values is found
        if (!(firstValueFound && secondValueFound))
        {
            pathBetweenNode(root.left, v1, v2);
        }
 
        // Ccopy of current state of firstValueFound
        // and secondValueFound flag
        Boolean localFirstValueFound = firstValueFound;
        Boolean localSecondValueFound = secondValueFound;
 
        // If the first value is found
        if (root.value == v1)
            firstValueFound = true;
 
        // If the second value is found
        if (root.value == v2)
            secondValueFound = true;
 
        Boolean localAdded = false;
 
        // If one of the value is found and the value
        // was not added to the stack yet or there was
        // only one value found and now both the values
        // are found and was not added to
        // the stack then add it
        if (((firstValueFound ^ secondValueFound)
            || ((localFirstValueFound ^ localSecondValueFound)
            && (firstValueFound && secondValueFound)))
            && !isAddedToStack)
        {
            localAdded = true;
            stack.Push(root);
        }
 
        // If none of the two values is found yet
        if (!(firstValueFound && secondValueFound))
        {
            pathBetweenNode(root.right, v1, v2);
        }
 
        if ((firstValueFound ^ secondValueFound)
            && !isAddedToStack && !localAdded)
            stack.Push(root);
 
        if ((firstValueFound ^ secondValueFound)
            && isAddedToStack)
            stack.Pop();
    }
 
    // Recursive function to print the
    // contents of a stack in reverse
    private static void print(Stack stack)
    {
 
        // If the stack is empty
        if (stack.Count==0)
            return;
 
        // Get the top value
        int value = stack.Pop().value;
 
        // Recursive call
        print(stack);
 
        // Print the Popped value
        Console.Write(value + " ");
    }
 
    // Driver code
    public static void Main(String []args)
    {
        Node root = new Node(0);
        root.left = new Node(1);
        root.right = new Node(2);
        root.left.left = new Node(3);
        root.left.right = new Node(4);
        root.right.left = new Node(5);
        root.right.right = new Node(6);
        root.left.left.left = new Node(7);
        root.left.right.left = new Node(8);
        root.left.right.right = new Node(9);
 
        // Find and print the path
        GFG pathBetweenNodes = new GFG(root);
        Stack stack
            = pathBetweenNodes.pathBetweenNode(7, 4);
        print(stack);
    }
}
 
// This code is contributed by Arnab Kundu


输出:
7 3 1 4