In Order Successor in Binary Search Tree

前端 未结 17 1771
孤独总比滥情好
孤独总比滥情好 2020-11-27 04:11

Given a node in a BST, how does one find the next higher key?

相关标签:
17条回答
  • 2020-11-27 04:47

    Here's an implementation without the need for parent links or intermediate structures (like a stack). This in-order successor function is a bit different to what most might be looking for since it operates on the key as opposed to the node. Also, it will find a successor of a key even if it is not present in the tree. Not too hard to change if you needed to, however.

    public class Node<T extends Comparable<T>> {
    
    private T data;
    private Node<T> left;
    private Node<T> right;
    
    public Node(T data, Node<T> left, Node<T> right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }
    
    /*
     * Returns the left-most node of the current node. If there is no left child, the current node is the left-most.
     */
    private Node<T> getLeftMost() {
        Node<T> curr = this;
        while(curr.left != null) curr = curr.left;
        return curr;
    }
    
    /*
     * Returns the right-most node of the current node. If there is no right child, the current node is the right-most.
     */
    private Node<T> getRightMost() {
        Node<T> curr = this;
        while(curr.right != null) curr = curr.right;
        return curr;
    }
    
    /**
     * Returns the in-order successor of the specified key.
     * @param key The key.
     * @return
     */
    public T getSuccessor(T key) {
        Node<T> curr = this;
        T successor = null;
        while(curr != null) {
            // If this.data < key, search to the right.
            if(curr.data.compareTo(key) < 0 && curr.right != null) {
                curr = curr.right;
            }
            // If this.data > key, search to the left.
            else if(curr.data.compareTo(key) > 0) { 
                // If the right-most on the left side has bigger than the key, search left.
                if(curr.left != null && curr.left.getRightMost().data.compareTo(key) > 0) {
                    curr = curr.left;
                }
                // If there's no left, or the right-most on the left branch is smaller than the key, we're at the successor.
                else {
                    successor = curr.data;
                    curr = null;
                }
            }
            // this.data == key...
            else {
                // so get the right-most data.
                if(curr.right != null) {
                    successor = curr.right.getLeftMost().data;
                }
                // there is no successor.
                else {
                    successor = null;
                }
                curr = null;
            }
        }
        return successor;
    }
    
    public static void main(String[] args) {
        Node<Integer> one, three, five, seven, two, six, four;
        one = new Node<Integer>(Integer.valueOf(1), null, null);
        three = new Node<Integer>(Integer.valueOf(3), null, null);
        five = new Node<Integer>(Integer.valueOf(5), null, null);
        seven = new Node<Integer>(Integer.valueOf(7), null, null);
        two = new Node<Integer>(Integer.valueOf(2), one, three);
        six = new Node<Integer>(Integer.valueOf(6), five, seven);
        four = new Node<Integer>(Integer.valueOf(4), two, six);
        Node<Integer> head = four;
        for(int i = 0; i <= 7; i++) {
            System.out.println(head.getSuccessor(i));
        }
    }
    }
    
    0 讨论(0)
  • 2020-11-27 04:47
    Node successor(int data) {
      return successor(root, data);
    }
    
    // look for the successor to data in the tree rooted at curr
    private Node successor(Node curr, int data) {
      if (curr == null) {
        return null;
      } else if (data < curr.data) {
        Node suc = successor(curr.left, data);
        // if a successor is found use it otherwise we know this node
        // is the successor since the target node was in this nodes left subtree
        return suc == null ? curr : suc;
      } else if (data > curr.data) {
        return successor(curr.right, data);
      } else {
        // we found the node so the successor might be the min of the right subtree
        return findMin(curr.right);
      }
    }
    
    private Node findMin(Node curr) {
      if (curr == null) {
        return null;
      }
    
      while (curr.left != null) {
        curr = curr.left;
      }
    
      return curr;
    }
    
    0 讨论(0)
  • 2020-11-27 04:48

    The general way depends on whether you have a parent link in your nodes or not.

    If you store the parent link

    Then you pick:

    1. The leftmost child of the right child, if your current node has a right child. If the right child has no left child, the right child is your inorder successor.
    2. Navigate up the parent ancestor nodes, and when you find a parent whose left child is the node you're currently at, the parent is the inorder successor of your original node.

    If you have right child, do this approach (case 1 above):

    inorder-when-right-child

    If you don't have a right child, do this approach (case 2 above):

    inorder-when-no-right-child

    If you don't store the parent link

    Then you need to run a complete scan of the tree, keeping track of the nodes, usually with a stack, so that you have the information necessary to basically do the same as the first method that relied on the parent link.

    0 讨论(0)
  • 2020-11-27 04:49

    These answers all seem overly complicated to me. We really don't need parent pointers or any auxiliary data structures like a stack. All we need to do is traverse the tree from the root in-order, set a flag as soon as we find the target node, and the next node in the tree that we visit will be the in order successor node. Here is a quick and dirty routine I wrote up.

    Node* FindNextInorderSuccessor(Node* root, int target, bool& done)
    {
        if (!root)
            return NULL;
    
        // go left
        Node* result = FindNextInorderSuccessor(root->left, target, done);
        if (result)
            return result;
    
        // visit
        if (done)
        {
            // flag is set, this must be our in-order successor node
            return root;
        }
        else
        {
            if (root->value == target)
            {
                // found target node, set flag so that we stop at next node
                done = true;
            }
        }
    
        // go right
        return FindNextInorderSuccessor(root->right, target, done);
    }
    
    0 讨论(0)
  • 2020-11-27 04:50

    If we perform a in order traversal then we visit the left subtree, then root node and finally the right subtree for each node in the tree. Performing a in order traversal will give us the keys of a binary search tree in ascending order, so when we refer to retrieving the in order successor of a node belonging to a binary search tree we mean what would be the next node in the sequence from the given node.

    Lets say we have a node R and we want its in order successor we would have the following cases.

    [1] The root R has a right node, so all we need to do is to traverse to the left most node of R->right.

    [2] The root R has no right node, in this case we traverse back up the tree following the parent links until the node R is a left child of its parent, when this occurs we have the parent node P as the in order successor.

    [3] We are at the extreme right node of the tree, in this case there is no in order successor.

    The implementation is based on the following node definition

    class node
    {
    private:
    node* left;
    node* right;
    node* parent
    int data;
    
    public:
    //public interface not shown, these are just setters and getters
    .......
    };
    
    //go up the tree until we have our root node a left child of its parent
    node* getParent(node* root)
    {
        if(root->parent == NULL)
            return NULL;
    
        if(root->parent->left == root)
            return root->parent;
        else
            return getParent(root->parent);
    }
    
    node* getLeftMostNode(node* root)
    {
        if(root == NULL)
            return NULL;
    
        node* left = getLeftMostNode(root->left);
        if(left)
            return left;
        return root;
    }
    
    //return the in order successor if there is one.
    //parameters - root, the node whose in order successor we are 'searching' for
    node* getInOrderSucc(node* root)
    {
        //no tree, therefore no successor
        if(root == NULL)
            return NULL;
    
        //if we have a right tree, get its left most node
        if(root->right)
            return getLeftMostNode(root->right);
        else
            //bubble up so the root node becomes the left child of its
            //parent, the parent will be the inorder successor.
            return getParent(root);
    }
    
    0 讨论(0)
  • 2020-11-27 04:50

    Doing this in Java

    TreeNode getSuccessor(TreeNode treeNode) {
        if (treeNode.right != null) {
             return getLeftMostChild(treeNode.right);
        } else {
            TreeNode p = treeNode.parent;
            while (p != null && treeNode == p.right) { // traverse upwards until there is no parent (at the last node of BST and when current treeNode is still the parent's right child
                treeNode = p;
                p = p.parent; // traverse upwards
            }
            return p; // returns the parent node
        }
    }
    
    TreeNode getLeftMostChild(TreeNode treeNode) {
        if (treeNode.left == null) {
            return treeNode;
        } else {
            return getLeftMostChild(treeNode.left);
        }
    }
    
    0 讨论(0)
提交回复
热议问题