📜  二进制搜索树中所有节点的预购后继者

📅  最后修改于: 2021-04-29 14:26:02             🧑  作者: Mango

考虑一个不允许重复的BST(二进制搜索树)。
在BST中给出了一个密钥。任务是在此BST中找到其预购继承者,即,如果我们对给定的BST应用预购遍历,则任务是找到与给定密钥相邻的密钥。

例子:
将以下密钥以相同的顺序插入BST中:51、39、31、54、92、42、21、10、26、52、36、47、82、5、62。
您将得到一个BST,如下所示:

插入给定数据后形成的二进制搜索树。

预购遍历:51 39 31 21 10 5 26 36 42 47 54 52 92 82 62

=====================================
Key       Pre-Order Successor
=====================================
51        39
39        31
31        21
21        10 
10        5
5         26
26        36
36        42
42        47
47        54
52        92
92        82
82        62
62        Do Not Exist. 

简单方法:解决此问题的简单方法是在给定的BST上应用预遍历,并将BST的密钥存储在数组中。接下来,在数组中搜索给定的键。如果存在,则其下一个键(可能不一定存在)是其预订后继。如果给定密钥在数组中不存在,则意味着给定密钥在BST中不存在,因此该密钥不能有任何预购后继。
但是该算法的时间复杂度为O(n)O(n)的空间复杂度,因此不是解决此问题的好方法。

高效的方法:基于以下观察结果,解决此问题的有效方法:

  • 在BST中搜索包含给定密钥的节点。
    • 如果BST中不存在该密钥,则此密钥不能有任何预购后继。
    • 如果它存在于BST中,那么此密钥可以有一个预购后继。请注意,如果密钥存在,则它不必具有预定的后继者。它取决于BST中给定密钥的位置
  • 如果包含给定键的节点具有左子节点,则其左子节点是其预订后继者。
  • 如果包含给定节点的节点有一个右子节点,但没有左子节点,则它的右子节点是其预订后继节点。
  • 如果包含给定键的节点是叶子,则您必须搜索具有右子级的最接近的祖先,并且此祖先的键大于给定键,即,您必须在给定键的左子树中搜索其最接近的祖先关键存在。还有另外两种情况:
    • 这样的祖先存在,如果存在,则此祖先的正确子级是给定密钥的预定后继者。
    • 这样的祖先不存在,如果存在,则给定密钥没有预购后继。

下面是上述方法的实现:

C
// C program to find pre-Order successor
// of a node in Binary Search Tree
#include
#include
 
// Declare a structure
struct Node{
    // Key to be stored in BST
    int key;
 
    // Pointer to left child
    struct Node *left;
 
    // Pointer to the right child
    struct Node *right;
     
    // Pointer to parent
    struct Node *parent;
};
 
// This function inserts node in BST
struct Node* insert(int key, struct Node *root,
                                   struct Node *parent)
{
     
    // If root is NULL, insert key here
    if(!root)
    {
        // Allocate memory dynamically
        struct Node *node = (struct Node*)malloc(sizeof(struct Node));
 
        // Validate malloc call
        if(node)
        {
            // Populate the object pointer to by
            // pointer named node
            node->key = key;
            node->left = node->right = NULL;
            node->parent = parent;
 
            // Return newly created node
            return node;
             
        }
        else
            // Malloc was not successful to satisfy our request,
            // given an appropriate message to the user
            printf("Could not allocate memory.");
         
    }
     
    // If this is a duplicate key then give a message to user
    else if(key == root->key)
        printf("Duplicates are not allowed in BST.");
     
    // If the key to be inserted is greater than the root's
    // key then it will go to the right subtree of
    // the tree with current root
    else if(key > root->key)
        root->right = insert(key, root->right,root);
     
    // If the key to be inserted is smaller than the
    // root's key then it will go to a left subtree of
    // the tree with current root
    else
        root->left = insert(key, root->left, root);
     
    // Return the root
    return root;
}
 
// This function searched for a given key in BST
struct Node* search(int key, struct Node *root)
{
    // Since the root is empty and hence key
    // does not exist in BST
    if(!root)
        return NULL;
     
    // Current root contains the given key,
    // so return current root
    else if( key == root->key)
        return root;
     
    // Key is greater than the root's key and therefore
    // we will search for this key in the right subtree of
    // tree with root as current root because of all of the keys
    // which are greater than the root's key exist in the right subtree   
    else if(key > root->key)
        return search(key, root->right);
     
    // Key is smaller than the root's key and therefore we will
    // search for this key in the left subtree of the tree with
    // root as the current root because of all of the keys which are
    // smaller than the root's key exists in the left subtree
    // search tree in the left subtree
    else
        return search(key, root->left);
     
}
 
// This function returns the node that contains the
// pre-order successor for the given key
struct Node* preOrderSuccessor(int key, struct Node *root){
 
    // Search for a node in BST that contains the given key
    struct Node *node = search(key, root);
 
    // There is no node in BST that contains the given key,
    // give an appropriate message to user
    if(!node){
        printf("%d do not exists in BST.\n", key);
        return NULL;
    }
 
 
    // There exist a node in BST that contains the given key
    // Apply our observations
    if(node->left)
        // If left child of the node that contains the
        // given key exist then it is the pre-order
        // successor for the given key
        return node->left;
 
    else if(node->right)
        // If right but not left child of node that contains
        // the given key exist then it is the pre-order
        // successor for the given key
        return node->right;
 
    else
    {
        // Node containing the key has neither left nor right child
        // which means that it is leaf node. In this case we will search
        // for its nearest ancestor with right child which has a key
        // greater than the given key
 
        // Since node is a leaf node so its parent is guaranteed to exist
        struct Node *temp = node->parent;
 
        // Search for nearest ancestor with right child that has
        // key greater than the given key
        while(temp){
            if(key < temp->key && temp->right)
                break;
            temp = temp->parent;
        }
 
        // If such an ancestor exist then right child of this ancestor
        // is the pre-order successor for the given otherwise there
        // do not exist any pre-order successor for the given key
        return temp ? temp->right : NULL;
    }
}
 
// This function traverse the BST in pre-order fashion
void preOrder(struct Node *root)
{
    if(root)
    {
        // First visit the root
        printf("%d ", root->key);
         
        // Next visit its left subtree
        preOrder(root->left);
         
        // Finally visit its right subtree
        preOrder(root->right);
    }
}
 
// Driver code
int main()
{
    // Declares a root for our BST
    struct Node *ROOT = NULL;
 
    // We will create 15 random integers in
    // range 0-99 to populate our BST
    int a[] = {51, 39, 31, 54, 92, 42, 21, 10,
                          26, 52, 36, 47, 82, 5, 62};
 
    int n = sizeof(a) / sizeof(a[0]);
     
    // Insert all elements into BST
    for(int i = 0 ; i < n; i++)
    {
        // Insert the generated number in BST
        printf("Inserting %2d.....", a[i]);
         
        ROOT = insert(a[i], ROOT, NULL);
        printf("Finished Insertion.\n");
    }
 
    // Apply pre-order traversal on BST
    printf("\nPre-Order Traversal : ");
    preOrder(ROOT);
 
    // Display pre-order Successors for all of the keys in BST
    printf("\n=====================================");
    printf("\n%-10s%s\n", "Key", "Pre-Order Successor");
    printf("=====================================\n");
 
    // This stores the pre-order successor for a given key
    struct Node *successor = NULL;
 
    // Iterate through all of the elements inserted
    // in BST to get their pre-order successor
    for(int i = 0 ; i < n; ++i)
    {
        // Get the pre-order successor for the given key
        successor = preOrderSuccessor(a[i], ROOT);
 
        if(successor)
            // Successor is not NULL and hence it contains
            // the pre-order successor for given key
            printf("%-10d%d\n", a[i], successor->key);
        else
            // Successor is NULL and hence given key do
            // not have a pre-order successor
            printf("%-10dDo Not Exist.\n", a[i]);
    }
 
    return 0;
}


Java
// Java program to find pre-Order successor
// of a node in Binary Search Tree
import java.util.*;
 
class GFG
{
 
// Declare a structure
static class Node
{
    // Key to be stored in BST
    int key;
 
    // Pointer to left child
    Node left;
 
    // Pointer to the right child
    Node right;
     
    // Pointer to parent
    Node parent;
};
 
// This function inserts node in BST
static Node insert(int key, Node root,
                            Node parent)
{
     
    // If root is null, insert key here
    if(root == null)
    {
        // Allocate memory dynamically
        Node node = new Node();
 
        // Validate malloc call
        if(node != null)
        {
            // Populate the object pointer to by
            // pointer named node
            node.key = key;
            node.left = node.right = null;
            node.parent = parent;
 
            // Return newly created node
            return node;
             
        }
        else
         
            // Malloc was not successful to
            // satisfy our request, given
            // an appropriate message to the user
            System.out.printf("Could not allocate memory.");
    }
     
    // If this is a duplicate key then
    // give a message to user
    else if(key == root.key)
        System.out.printf("Duplicates are not" +
                            " allowed in BST.");
     
    // If the key to be inserted is greater than
    // the root's key then it will go to the
    // right subtree of the tree with current root
    else if(key > root.key)
        root.right = insert(key, root.right, root);
     
    // If the key to be inserted is smaller than the
    // root's key then it will go to a left subtree
    // of the tree with current root
    else
        root.left = insert(key, root.left, root);
     
    // Return the root
    return root;
}
 
// This function searched for a given key in BST
static Node search(int key, Node root)
{
    // Since the root is empty and hence
    // key does not exist in BST
    if(root == null)
        return null;
     
    // Current root contains the given key,
    // so return current root
    else if( key == root.key)
        return root;
     
    // Key is greater than the root's key and 
    // therefore we will search for this key
    // in the right subtree of tree with root
    // as current root because of all of the keys
    // which are greater than the root's key
    // exist in the right subtree
    else if(key > root.key)
        return search(key, root.right);
     
    // Key is smaller than the root's key and
    // therefore we will search for this key
    // in the left subtree of the tree with root
    // as the current root because of all of the keys
    // which are smaller than the root's key exists in
    // the left subtree search tree in the left subtree
    else
        return search(key, root.left);
}
 
// This function returns the node
// that contains the pre-order successor
// for the given key
static Node preOrderSuccessor(int key,
                              Node root)
{
 
    // Search for a node in BST
    // that contains the given key
    Node node = search(key, root);
 
    // There is no node in BST
    // that contains the given key,
    // give an appropriate message to user
    if(node == null)
    {
        System.out.printf("%d do not exists" +
                           " in BST.\n", key);
        return null;
    }
 
    // There exist a node in BST that contains
    // the given key. Apply our observations
    if(node.left != null)
     
        // If left child of the node that
        // contains the given key exist
        // then it is the pre-order successor
        // for the given key
        return node.left;
 
    else if(node.right != null)
     
        // If right but not left child of node
        // that contains the given key exist 
        // then it is the pre-order successor
        // for the given key
        return node.right;
 
    else
    {
        // Node containing the key has neither left
        // nor right child which means that it is
        // leaf node. In this case we will search
        // for its nearest ancestor with right child
        // which has a key greater than the given key
 
        // Since node is a leaf node
        // so its parent is guaranteed to exist
        Node temp = node.parent;
 
        // Search for nearest ancestor with right child
        // that has key greater than the given key
        while(temp != null)
        {
            if(key < temp.key && temp.right != null)
                break;
            temp = temp.parent;
        }
 
        // If such an ancestor exist then right child
        // of this ancestor is the pre-order successor
        // for the given otherwise there do not exist
        // any pre-order successor for the given key
        return temp != null ? temp.right : null;
    }
}
 
// This function traverse the BST
// in pre-order fashion
static void preOrder(Node root)
{
    if(root != null)
    {
        // First visit the root
        System.out.printf("%d ", root.key);
         
        // Next visit its left subtree
        preOrder(root.left);
         
        // Finally visit its right subtree
        preOrder(root.right);
    }
}
 
// Driver code
public static void main(String args[])
{
    // Declares a root for our BST
    Node ROOT = null;
 
    // We will create 15 random integers in
    // range 0-99 to populate our BST
    int a[] = {51, 39, 31, 54, 92, 42, 21, 10,
                26, 52, 36, 47, 82, 5, 62};
 
    int n = a.length;
     
    // Insert all elements into BST
    for(int i = 0 ; i < n; i++)
    {
        // Insert the generated number in BST
        System.out.printf("Inserting %2d.....", a[i]);
         
        ROOT = insert(a[i], ROOT, null);
        System.out.printf("Finished Insertion.\n");
    }
 
    // Apply pre-order traversal on BST
    System.out.printf("\nPre-Order Traversal : ");
    preOrder(ROOT);
 
    // Display pre-order Successors
    // for all of the keys in BST
    System.out.printf("\n=====================================");
    System.out.printf("\n%-10s%s\n", "Key",
                    "Pre-Order Successor");
    System.out.printf("=====================================\n");
 
    // This stores the pre-order successor
    // for a given key
    Node successor = null;
 
    // Iterate through all of the elements inserted
    // in BST to get their pre-order successor
    for(int i = 0 ; i < n; ++i)
    {
        // Get the pre-order successor
        // for the given key
        successor = preOrderSuccessor(a[i], ROOT);
 
        if(successor != null)
         
            // Successor is not null and hence
            // it contains the pre-order
            // successor for given key
            System.out.printf("%-10d%d\n", a[i],
                                 successor.key);
        else
            // Successor is null and hence given key do
            // not have a pre-order successor
            System.out.printf("%-10dDo Not Exist.\n", a[i]);
    }
}
}
 
// This code is contributed by Arnab Kundu


Python3
# Python3 program to find pre-Order successor
# of a node in Binary Search Tree
 
# Declare a structure
class Node:
     
    def __init__(self):
         
        # Key to be stored in BST
        self.key = 0
 
        # Pointer to left child
        self.left = None
 
        # Pointer to the right child
        self.right = None
 
        # Pointer to parent
        self.parent = None
 
# This function inserts node in BST
def insert(key: int, root: Node, parent: Node):
     
    # If root is None, insert key here
    if not root:
 
        # Allocate memory dynamically
        node = Node()
 
        # Validate malloc call
        if (node):
 
            # Populate the object pointer to by
            # pointer named node
            node.key = key
            node.left = node.right = None
            node.parent = parent
 
            # Return newly created node
            return node
 
        else:
             
            # Malloc was not successful to satisfy our request,
            # given an appropriate message to the user
            print("Could not allocate memory.")
 
    # If this is a duplicate key then give a message to user
    elif (key == root.key):
        print("Duplicates are not allowed in BST.")
 
    # If the key to be inserted is greater than the root's
    # key then it will go to the right subtree of
    # the tree with current root
    elif (key > root.key):
        root.right = insert(key, root.right, root)
 
    # If the key to be inserted is smaller than the
    # root's key then it will go to a left subtree of
    # the tree with current root
    else:
        root.left = insert(key, root.left, root)
 
    # Return the root
    return root
 
# This function searched for a given key in BST
def search(key: int, root: Node):
 
    # Since the root is empty and hence key
    # does not exist in BST
    if not root:
        return None
 
    # Current root contains the given key,
    # so return current root
    elif (key == root.key):
        return root
 
    # Key is greater than the root's key and therefore
    # we will search for this key in the right subtree
    # of tree with root as current root because of all
    # of the keys which are greater than the root's key
    # exist in the right subtree
    elif (key > root.key):
        return search(key, root.right)
 
    # Key is smaller than the root's key and therefore
    # we will search for this key in the left subtree
    # of the tree with root as the current root because
    # of all of the keys which are smaller than the
    # root's key exists in the left subtree search
    # tree in the left subtree
    else:
        return search(key, root.left)
 
# This function returns the node that contains the
# pre-order successor for the given key
def preOrderSuccessor(key: int, root: Node):
     
    # Search for a node in BST that
    # contains the given key
    node = search(key, root)
 
    # There is no node in BST that contains
    # the given key, give an appropriate
    # message to user
    if not node:
        print("%d do not exists in BST.\n" % key, end = "")
        return None
 
    # There exist a node in BST that contains the
    # given key. Apply our observations
    if (node.left):
         
        # If left child of the node that contains the
        # given key exist then it is the pre-order
        # successor for the given key
        return node.left
 
    elif (node.right):
         
        # If right but not left child of node that
        # contains the given key exist then it is
        # the pre-order successor for the given key
        return node.right
 
    else:
 
        # Node containing the key has neither left
        # nor right child which means that it is
        # leaf node. In this case we will search
        # for its nearest ancestor with right
        # child which has a key greater than
        # the given key
 
        # Since node is a leaf node so its parent
        # is guaranteed to exist
        temp = node.parent
 
        # Search for nearest ancestor with right
        # child that has key greater than the
        # given key
        while (temp):
            if (key < temp.key and temp.right):
                break
             
            temp = temp.parent
 
        # If such an ancestor exist then right child
        # of this ancestor is the pre-order successor
        # for the given otherwise there do not exist
        # any pre-order successor for the given key
        return temp.right if temp != None else None
 
# This function traverse the BST in
# pre-order fashion
def preOrder(root: Node):
 
    if (root):
         
        # First visit the root
        print("%d " % root.key, end = "")
 
        # Next visit its left subtree
        preOrder(root.left)
 
        # Finally visit its right subtree
        preOrder(root.right)
 
# Driver code
if __name__ == "__main__":
 
    # Declares a root for our BST
    ROOT = None
 
    # We will create 15 random integers in
    # range 0-99 to populate our BST
    a = [ 51, 39, 31, 54, 92, 42, 21,
          10, 26, 52, 36, 47, 82, 5, 62 ]
 
    n = len(a)
 
    # Insert all elements into BST
    for i in range(n):
 
        # Insert the generated number in BST
        print("Inserting %2d....." % a[i], end = "")
 
        ROOT = insert(a[i], ROOT, None)
        print("Finished Insertion.")
 
    # Apply pre-order traversal on BST
    print("\nPre-Order Traversal : ", end = "")
    preOrder(ROOT)
 
    # Display pre-order Successors for all of the keys in BST
    print("\n=====================================", end = "")
    print("\n%-10s%s\n" % ("Key", "Pre-Order Successor"), end = "")
    print("=====================================")
 
    # This stores the pre-order successor for a given key
    successor = None
 
    # Iterate through all of the elements inserted
    # in BST to get their pre-order successor
    for i in range(n):
 
        # Get the pre-order successor for the given key
        successor = preOrderSuccessor(a[i], ROOT)
 
        if (successor):
             
            # Successor is not None and hence it contains
            # the pre-order successor for given key
            print("%-10d%d" % (a[i], successor.key))
        else:
             
            # Successor is None and hence given key do
            # not have a pre-order successor
            print("%-10dDo Not Exist." % a[i])
 
# This code is contributed by sanjeev2552


输出:
Inserting 51.....Finished Insertion.
Inserting 39.....Finished Insertion.
Inserting 31.....Finished Insertion.
Inserting 54.....Finished Insertion.
Inserting 92.....Finished Insertion.
Inserting 42.....Finished Insertion.
Inserting 21.....Finished Insertion.
Inserting 10.....Finished Insertion.
Inserting 26.....Finished Insertion.
Inserting 52.....Finished Insertion.
Inserting 36.....Finished Insertion.
Inserting 47.....Finished Insertion.
Inserting 82.....Finished Insertion.
Inserting  5.....Finished Insertion.
Inserting 62.....Finished Insertion.

Pre-Order Traversal : 51 39 31 21 10 5 26 36 42 47 54 52 92 82 62 
=====================================
Key       Pre-Order Successor
=====================================
51        39
39        31
31        21
54        52
92        82
42        47
21        10
10        5
26        36
52        92
36        42
47        54
82        62
5         26
62        Do Not Exist.