📜  二叉搜索树的预排序中的叶节点

📅  最后修改于: 2021-05-25 00:13:50             🧑  作者: Mango

给定二进制搜索树的遍历顺序。任务是从给定的预定顺序打印二进制搜索树的叶节点。

例子:

Input : preorder[] = {890, 325, 290, 530, 965};
Output : 290 530 965
Explanation : Tree represented is,
      890
     /   \
  325    965
  /  \
290   530

Input : preorder[] = { 3, 2, 4 };
Output : 2 4

方法1 :(简单)

这个想法是找到Iorder,然后以预排序方式(使用有序和后序遍历)遍历树,同时遍历打印叶节点。

如何使用表示有序和预序遍历的两个数组以预序方式遍历?
我们迭代预排序数组,并为每个元素在顺序数组中找到该元素。对于搜索,我们可以使用二进制搜索,因为二进制搜索树的有序遍历始终是排序的。现在,对于预排序数组的每个元素,在二进制搜索中,我们设置范围[L,R]。
当L == R时,找到叶节点。因此,最初,对于预排序数组的第一个元素(即根),L = 0和R = n – 1。现在,要搜索根的左子树上的元素,请设置L = 0且R =根的索引–1。此外,对于右子树的所有元素,请设置L =根的索引+ 1和R = n -1 。
递归地,遵循此,直到L ==R。

以下是此方法的实现:

C++
// C++ program to print leaf node from
// preorder of binary search tree.
#include
using namespace std;
  
// Binary Search
int binarySearch(int inorder[], int l, int r, int d)
{
    int mid = (l + r)>>1;
  
    if (inorder[mid] == d)
        return mid;
  
    else if (inorder[mid] > d)
        return binarySearch(inorder, l, mid - 1, d);
  
    else
        return binarySearch(inorder, mid + 1, r, d);
}
  
// Function to print Leaf Nodes by doing preorder
// traversal of tree using preorder and inorder arrays.
void leafNodesRec(int preorder[], int inorder[],
                  int l, int r, int *ind, int n)
{
    // If l == r, therefore no right or left subtree.
    // So, it must be leaf Node, print it.
    if(l == r)
    {
        printf("%d ", inorder[l]);
        *ind = *ind + 1;
        return;
    }
  
    // If array is out of bound, return.
    if (l < 0 || l > r || r >= n)
        return;
  
    // Finding the index of preorder element
    // in inorder array using binary search.
    int loc = binarySearch(inorder, l, r, preorder[*ind]);
  
    // Incrementing the index.
    *ind = *ind + 1;
  
    // Finding on the left subtree.
    leafNodesRec(preorder, inorder, l, loc - 1, ind, n);
  
    // Finding on the right subtree.
    leafNodesRec(preorder, inorder, loc + 1, r, ind, n);
}
  
// Finds leaf nodes from given preorder traversal.
void leafNodes(int preorder[], int n)
{
    int inorder[n];  // To store inorder traversal
  
    // Copy the preorder into another array.
    for (int i = 0; i < n; i++)
        inorder[i] = preorder[i];
  
    // Finding the inorder by sorting the array.
    sort(inorder, inorder + n);
  
    // Point to the index in preorder.
    int ind = 0;
  
    // Print the Leaf Nodes.
    leafNodesRec(preorder, inorder, 0, n - 1, &ind, n);
}
  
// Driven Program
int main()
{
    int preorder[] = { 890, 325, 290, 530, 965 };
    int n = sizeof(preorder)/sizeof(preorder[0]);
  
    leafNodes(preorder, n);
    return 0;
}


Java
// Java program to print leaf node from
// preorder of binary search tree.
import java.util.*;
  
class GFG
{
  
// Binary Search
static int binarySearch(int inorder[], int l, 
                        int r, int d)
{
    int mid = (l + r) >> 1;
  
    if (inorder[mid] == d)
        return mid;
  
    else if (inorder[mid] > d)
        return binarySearch(inorder, l,
                            mid - 1, d);
  
    else
        return binarySearch(inorder, 
                            mid + 1, r, d);
}
  
// Point to the index in preorder.
static int ind;
  
// Function to print Leaf Nodes by 
// doing preorder traversal of tree
// using preorder and inorder arrays.
static void leafNodesRec(int preorder[], 
                         int inorder[],
                         int l, int r, int n)
{
    // If l == r, therefore no right or left subtree.
    // So, it must be leaf Node, print it.
    if(l == r)
    {
        System.out.printf("%d ", inorder[l]);
        ind = ind + 1;
        return;
    }
  
    // If array is out of bound, return.
    if (l < 0 || l > r || r >= n)
        return;
  
    // Finding the index of preorder element
    // in inorder array using binary search.
    int loc = binarySearch(inorder, l, r, 
                           preorder[ind]);
  
    // Incrementing the index.
    ind = ind + 1;
  
    // Finding on the left subtree.
    leafNodesRec(preorder, inorder,
                    l, loc - 1, n);
  
    // Finding on the right subtree.
    leafNodesRec(preorder, inorder, 
                    loc + 1, r, n);
}
  
// Finds leaf nodes from given preorder traversal.
static void leafNodes(int preorder[], int n)
{
    // To store inorder traversal
    int inorder[] = new int[n]; 
  
    // Copy the preorder into another array.
    for (int i = 0; i < n; i++)
        inorder[i] = preorder[i];
  
    // Finding the inorder by sorting the array.
    Arrays.sort(inorder);
  
    // Print the Leaf Nodes.
    leafNodesRec(preorder, inorder, 0, n - 1, n);
}
  
// Driver Code
public static void main(String args[])
{
    int preorder[] = { 890, 325, 290, 530, 965 };
    int n = preorder.length;
  
    leafNodes(preorder, n);
}
}
  
// This code is contributed by Arnab Kundu


Python3
# Python3 program to print leaf node from
# preorder of binary search tree.
  
# Binary Search
def binarySearch(inorder, l, r, d):
  
    mid = (l + r) >> 1
    if (inorder[mid] == d):
        return mid
    elif (inorder[mid] > d):
        return binarySearch(inorder, l,
                            mid - 1, d)
    else:
        return binarySearch(inorder, 
                            mid + 1, r, d)
  
# Function to prLeaf Nodes by doing 
# preorder traversal of tree using 
# preorder and inorder arrays.
def leafNodesRec(preorder, inorder, 
                      l, r, ind, n):
  
    # If l == r, therefore no right or left subtree.
    # So, it must be leaf Node, print it.
    if(l == r):
        print(inorder[l], end = " ")
        ind[0] = ind[0] + 1
        return
  
    # If array is out of bound, return.
    if (l < 0 or l > r or r >= n):
        return
  
    # Finding the index of preorder element
    # in inorder array using binary search.
    loc = binarySearch(inorder, l, r, 
                       preorder[ind[0]])
  
    # Incrementing the index.
    ind[0] = ind[0] + 1
  
    # Finding on the left subtree.
    leafNodesRec(preorder, inorder,     
                 l, loc - 1, ind, n)
  
    # Finding on the right subtree.
    leafNodesRec(preorder, inorder, 
                 loc + 1, r, ind, n)
  
# Finds leaf nodes from 
# given preorder traversal.
def leafNodes(preorder, n):
  
    # To store inorder traversal
    inorder = [0] * n 
      
    # Copy the preorder into another array.
    for i in range(n):
        inorder[i] = preorder[i]
  
    # Finding the inorder by sorting the array.
    inorder.sort()
      
    # Poto the index in preorder.
    ind = [0]
      
    # Print the Leaf Nodes.
    leafNodesRec(preorder, inorder, 0,
                 n - 1, ind, n)
  
  
# Driver Code
preorder = [890, 325, 290, 530, 965]
n = len(preorder)
leafNodes(preorder, n)
  
# This code is contributed
# by SHUBHAMSINGH10


C#
// C# program to print leaf node from
// preorder of binary search tree.
using System;
  
class GFG
{
  
// Binary Search
static int binarySearch(int []inorder, int l, 
                        int r, int d)
{
    int mid = (l + r) >> 1;
  
    if (inorder[mid] == d)
        return mid;
  
    else if (inorder[mid] > d)
        return binarySearch(inorder, l,
                            mid - 1, d);
  
    else
        return binarySearch(inorder, 
                            mid + 1, r, d);
}
  
// Point to the index in preorder.
static int ind;
  
// Function to print Leaf Nodes by 
// doing preorder traversal of tree
// using preorder and inorder arrays.
static void leafNodesRec(int []preorder, 
                        int []inorder,
                        int l, int r, int n)
{
    // If l == r, therefore no right or left subtree.
    // So, it must be leaf Node, print it.
    if(l == r)
    {
        Console.Write("{0} ", inorder[l]);
        ind = ind + 1;
        return;
    }
  
    // If array is out of bound, return.
    if (l < 0 || l > r || r >= n)
        return;
  
    // Finding the index of preorder element
    // in inorder array using binary search.
    int loc = binarySearch(inorder, l, r, 
                        preorder[ind]);
  
    // Incrementing the index.
    ind = ind + 1;
  
    // Finding on the left subtree.
    leafNodesRec(preorder, inorder,
                    l, loc - 1, n);
  
    // Finding on the right subtree.
    leafNodesRec(preorder, inorder, 
                    loc + 1, r, n);
}
  
// Finds leaf nodes from given preorder traversal.
static void leafNodes(int []preorder, int n)
{
    // To store inorder traversal
    int []inorder = new int[n]; 
  
    // Copy the preorder into another array.
    for (int i = 0; i < n; i++)
        inorder[i] = preorder[i];
  
    // Finding the inorder by sorting the array.
    Array.Sort(inorder);
  
    // Print the Leaf Nodes.
    leafNodesRec(preorder, inorder, 0, n - 1, n);
}
  
// Driver Code
public static void Main(String []args)
{
    int []preorder = { 890, 325, 290, 530, 965 };
    int n = preorder.Length;
  
    leafNodes(preorder, n);
}
}
  
// This code is contributed by Rajput-Ji


C++
// Stack based C++ program to print leaf nodes
// from preorder traversal.
#include
using namespace std;
  
// Print the leaf node from the given preorder of BST.
void leafNode(int preorder[], int n)
{
    stack s;
    for (int i = 0, j = 1; j < n; i++, j++)
    {
        bool found = false;
  
        if (preorder[i] > preorder[j])
            s.push(preorder[i]);
  
        else
        {
            while (!s.empty())
            {
                if (preorder[j] > s.top())
                {
                    s.pop();
                    found = true;
                }
                else
                    break;
            }
        }
  
        if (found)
            cout << preorder[i] << " ";
    }
  
    // Since rightmost element is always leaf node.
    cout << preorder[n - 1];
}
  
// Driver code
int main()
{
    int preorder[] = { 890, 325, 290, 530, 965 };
    int n = sizeof(preorder)/sizeof(preorder[0]);
  
    leafNode(preorder, n);
    return 0;
}


Java
// Stack based Java program to print leaf nodes 
// from preorder traversal.
import java.util.*;
class GfG {
  
// Print the leaf node from the given preorder of BST. 
static void leafNode(int preorder[], int n) 
{ 
    Stack s = new Stack (); 
    for (int i = 0, j = 1; j < n; i++, j++) 
    { 
        boolean found = false; 
  
        if (preorder[i] > preorder[j]) 
            s.push(preorder[i]); 
  
        else
        { 
            while (!s.isEmpty()) 
            { 
                if (preorder[j] > s.peek()) 
                { 
                    s.pop(); 
                    found = true; 
                } 
                else
                    break; 
            } 
        } 
  
        if (found) 
            System.out.print(preorder[i] + " "); 
    } 
  
    // Since rightmost element is always leaf node. 
    System.out.println(preorder[n - 1]); 
} 
  
// Driver code 
public static void main(String[] args) 
{ 
    int preorder[] = { 890, 325, 290, 530, 965 }; 
    int n = preorder.length; 
  
    leafNode(preorder, n); 
} 
}


Python3
# Stack based Python program to print 
# leaf nodes from preorder traversal. 
  
# Print the leaf node from the given 
# preorder of BST. 
def leafNode(preorder, n):
    s = [] 
    i = 0
    for j in range(1, n):
        found = False
        if preorder[i] > preorder[j]: 
            s.append(preorder[i])
  
        else:
            while len(s) != 0:
                if preorder[j] > s[-1]:
                    s.pop(-1)
                    found = True
                else:
                    break
  
        if found: 
            print(preorder[i], end = " ")
        i += 1
  
    # Since rightmost element is 
    # always leaf node. 
    print(preorder[n - 1])
  
# Driver code 
if __name__ == '__main__':
    preorder = [890, 325, 290, 530, 965] 
    n = len(preorder) 
  
    leafNode(preorder, n)
  
# This code is contributed by PranchalK


C#
using System;
using System.Collections.Generic;
  
// Stack based C# program to print leaf nodes  
// from preorder traversal. 
public class GfG
{
  
// Print the leaf node from the given preorder of BST.  
public static void leafNode(int[] preorder, int n)
{
    Stack s = new Stack ();
    for (int i = 0, j = 1; j < n; i++, j++)
    {
        bool found = false;
  
        if (preorder[i] > preorder[j])
        {
            s.Push(preorder[i]);
        }
  
        else
        {
            while (s.Count > 0)
            {
                if (preorder[j] > s.Peek())
                {
                    s.Pop();
                    found = true;
                }
                else
                {
                    break;
                }
            }
        }
  
        if (found)
        {
            Console.Write(preorder[i] + " ");
        }
    }
  
    // Since rightmost element is always leaf node.  
    Console.WriteLine(preorder[n - 1]);
}
  
// Driver code  
public static void Main(string[] args)
{
    int[] preorder = new int[] {890, 325, 290, 530, 965};
    int n = preorder.Length;
  
    leafNode(preorder, n);
}
}
  
  // This code is contributed by Shrikant13


输出:

290 530 965

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

方法2 :(使用堆栈)

这个想法是使用二进制搜索树和堆栈的属性。
使用两个指向数组的指针i和j遍历数组,最初i = 0和j =1。每当a [i]> a [j]时,我们可以说a [j]是a [i]的左部分,因为顺序遍历遵循“访问”->“左”->“右”。因此,我们将a [i]推入堆栈。
对于违反规则的那些点,我们开始从堆栈中弹出元素,直到a [i]>堆栈的顶部元素,然后在不出现时断开,并打印相应的j值。
算法:

1. Set i = 0, j = 1.
2. Traverse the preorder array.
3. If a[i] > a[j], push a[i] to the stack.
4. Else
   While (stack is not empty)
     if (a[j] > top of stack)
       pop element from the stack;
       set found = true;
     else
       break;
5. if (found == true)
     print a[i];

该算法如何工作?
顺序遍历遍历的顺序为:访问,向左,向右。
而且我们知道BST中任何节点的左节点始终小于该节点。因此,预遍历将首先从根节点遍历到最左边的节点。因此,预排序将首先以降序排列。现在,在降序之后,可能存在一个更大的节点或打破了降序的节点。因此,可能会有这样的情况:

在情况1中,20是叶节点,而在情况2中,20不是叶节点。
因此,我们的问题是如何确定是否必须将20打印为叶节点?
这是使用堆栈解决的。
在情况1和情况2上运行上述算法时,当i = 2和j = 3时,两种情况下的堆栈状态都相同:

因此,节点65将从堆栈中弹出20和50。这是因为65是20之前的节点的右子节点。我们使用找到的变量存储此信息。因此,20是一个根节点。
在第2种情况下,40将无法从堆栈中弹出任何元素。因为40是20之后的节点的右节点,所以20不是叶节点。

注意:在算法中,我们将无法检查最右节点或预排序中最右元素的叶节点的状况。因此,只需打印最右边的节点,因为我们知道在预遍历中这将始终是叶节点。

以下是此方法的实现:

C++

// Stack based C++ program to print leaf nodes
// from preorder traversal.
#include
using namespace std;
  
// Print the leaf node from the given preorder of BST.
void leafNode(int preorder[], int n)
{
    stack s;
    for (int i = 0, j = 1; j < n; i++, j++)
    {
        bool found = false;
  
        if (preorder[i] > preorder[j])
            s.push(preorder[i]);
  
        else
        {
            while (!s.empty())
            {
                if (preorder[j] > s.top())
                {
                    s.pop();
                    found = true;
                }
                else
                    break;
            }
        }
  
        if (found)
            cout << preorder[i] << " ";
    }
  
    // Since rightmost element is always leaf node.
    cout << preorder[n - 1];
}
  
// Driver code
int main()
{
    int preorder[] = { 890, 325, 290, 530, 965 };
    int n = sizeof(preorder)/sizeof(preorder[0]);
  
    leafNode(preorder, n);
    return 0;
}

Java

// Stack based Java program to print leaf nodes 
// from preorder traversal.
import java.util.*;
class GfG {
  
// Print the leaf node from the given preorder of BST. 
static void leafNode(int preorder[], int n) 
{ 
    Stack s = new Stack (); 
    for (int i = 0, j = 1; j < n; i++, j++) 
    { 
        boolean found = false; 
  
        if (preorder[i] > preorder[j]) 
            s.push(preorder[i]); 
  
        else
        { 
            while (!s.isEmpty()) 
            { 
                if (preorder[j] > s.peek()) 
                { 
                    s.pop(); 
                    found = true; 
                } 
                else
                    break; 
            } 
        } 
  
        if (found) 
            System.out.print(preorder[i] + " "); 
    } 
  
    // Since rightmost element is always leaf node. 
    System.out.println(preorder[n - 1]); 
} 
  
// Driver code 
public static void main(String[] args) 
{ 
    int preorder[] = { 890, 325, 290, 530, 965 }; 
    int n = preorder.length; 
  
    leafNode(preorder, n); 
} 
} 

Python3

# Stack based Python program to print 
# leaf nodes from preorder traversal. 
  
# Print the leaf node from the given 
# preorder of BST. 
def leafNode(preorder, n):
    s = [] 
    i = 0
    for j in range(1, n):
        found = False
        if preorder[i] > preorder[j]: 
            s.append(preorder[i])
  
        else:
            while len(s) != 0:
                if preorder[j] > s[-1]:
                    s.pop(-1)
                    found = True
                else:
                    break
  
        if found: 
            print(preorder[i], end = " ")
        i += 1
  
    # Since rightmost element is 
    # always leaf node. 
    print(preorder[n - 1])
  
# Driver code 
if __name__ == '__main__':
    preorder = [890, 325, 290, 530, 965] 
    n = len(preorder) 
  
    leafNode(preorder, n)
  
# This code is contributed by PranchalK

C#

using System;
using System.Collections.Generic;
  
// Stack based C# program to print leaf nodes  
// from preorder traversal. 
public class GfG
{
  
// Print the leaf node from the given preorder of BST.  
public static void leafNode(int[] preorder, int n)
{
    Stack s = new Stack ();
    for (int i = 0, j = 1; j < n; i++, j++)
    {
        bool found = false;
  
        if (preorder[i] > preorder[j])
        {
            s.Push(preorder[i]);
        }
  
        else
        {
            while (s.Count > 0)
            {
                if (preorder[j] > s.Peek())
                {
                    s.Pop();
                    found = true;
                }
                else
                {
                    break;
                }
            }
        }
  
        if (found)
        {
            Console.Write(preorder[i] + " ");
        }
    }
  
    // Since rightmost element is always leaf node.  
    Console.WriteLine(preorder[n - 1]);
}
  
// Driver code  
public static void Main(string[] args)
{
    int[] preorder = new int[] {890, 325, 290, 530, 965};
    int n = preorder.Length;
  
    leafNode(preorder, n);
}
}
  
  // This code is contributed by Shrikant13

输出:

290 530 965

时间复杂度: O(n)

二叉搜索树的预排序中的叶节点(使用递归)