如何在二叉搜索树中删除具有2个子节点的节点?

时间:2011-11-28 07:31:20

标签: data-structures binary-search-tree

如何删除二叉树中包含2个子节点的节点?

有什么方法可以删除吗?我用Google搜索了一下。但是没有清楚地了解它。有人用图解表示来解释它吗?

How to delete the node '5' from the this image and what might be the outcome?

8 个答案:

答案 0 :(得分:13)

将所述节点替换为右侧最左侧的孩子,或者左侧最右侧的孩子。然后,您从底部删除它被替换为。

删除五个可能会产生一棵树,其根为3或根为18,具体取决于您所采用的方向。

看起来你从这个网站获得了这张图片:http://www.algolist.net/Data_structures/Binary_search_tree/Removal

它也会显示您想要的图像算法。

答案 1 :(得分:3)

删除节点有三种情况可能..

  1. Node是一个叶子节点:这是一个简单的例子,弄清楚这个节点是父节点的左节点还是右节点,并将null设置为父节点的子节点。
  2. 节点有一个子节点:在此节点的父节点和子节点之间建立直接链接。
  3. Node有两个孩子:这有点棘手......这涉及的步骤是。
    1. 首先找到此节点的后继者(或前身)。
    2. 从树中删除后继者(或前任)。
    3. 用后继者(或前身)
    4. 替换要删除的节点
  4. 在了解删除概念之前,我们应该理解后继者和前辈的概念

    后继者:在二叉树中,节点的后继者是树的最小节点,该节点严格地大于该节点。

    节点有两种可能的情况

    • 节点有正确的子节点:在这种情况下,右子树的最左边的子节点将是后继节点。

    • 节点没有子节点:转到父节点,找到该节点属于左子树的节点。

      public Node sucessor(Node node) {
      Node sucessor = null;
      if (node.getRightNode() != null) {
          Node newNode = node.getRightNode();
          while (newNode != null) {
              sucessor = newNode;
              newNode = newNode.getLeftNode();
          }
      } else {
          sucessor = findRightParent(node);
      }
      return sucessor;
      }
      private Node findRightParent(Node node) {
      Node newNode = null;
      if (node.getParentNode() != null) {
          if (node.getParentNode().getLeftNode() == node) {
              newNode = node.getParentNode();
          } else {
              newNode = findRightParent(node.getParentNode());
          }
      }
      return newNode;
      }
      

    现在删除逻辑

         public void deleteNode(Node node) {
        // Node is a leaf node //
        if( node.getLeftNode() == null && node.getRightNode() == null){
            if(isRightNode(node.getParentNode(), node)){
                node.getParentNode().setRightNode(null);
            }else{
                node.getParentNode().setLeftNode(null);
            }
            // Only left child is there//
        }else if( node.getLeftNode() != null && node.getRightNode() == null){
            if(isRightNode(node.getParentNode(), node)){
                node.getParentNode().setRightNode(node.getLeftNode());
            }else{
                node.getParentNode().setLeftNode(node.getLeftNode());
            }
            // Only Right child is there //
        }else if( node.getLeftNode() == null && node.getRightNode() != null){
            if( isRightNode(node.getParentNode(), node)){
                node.getParentNode().setRightNode(node.getRightNode());
            }else{
                node.getParentNode().setLeftNode(node.getRightNode());
            }
            // Both Left and Right children are their//
        }else{
            Node psNode = predessor(node);
            deleteNode(psNode);
            psNode.setParentNode(node.getParentNode());
            psNode.setLeftNode(node.getLeftNode());
            psNode.setRightNode(node.getRightNode());
            if( isRightNode(node.getParentNode(), node)){
                node.getParentNode().setRightNode(psNode);
            }else{
                node.getParentNode().setLeftNode(psNode);
            }
        }
    
        }
    

    解决方案取自http://coder2design.com/binary-tree/

    他们还用完整的源代码解释了遍历和插入的流程。

答案 2 :(得分:1)

维基百科的文章很好地描述了BST:

http://en.wikipedia.org/wiki/Binary_search_tree

删除包含2个子节点的节点时,如果是5,则可以使用右子树中的最小值节点或左子树中的最大值节点替换已删除的节点。

答案 3 :(得分:1)

一个简单易行的解决方案:

            Node* findMaxNode(Node* root)
            {
                if(root->right == NULL) return root;
                findMaxNode(root->right);
            }


            Node* DeleteNodeInBST(Node* root,int data)
            {
                //base case when not found or found then recursion breaks

                if(root == NULL) return root;
                else if(root->data > data) root->left = DeleteNodeInBST(root->left, data);
                else if(root->data < data) root->right = DeleteNodeInBST(root->right, data);
                else
                {
                    //when the node to be deleted is found
                    //Four possibilities

                    //case1: When the node to be deleted has no children
                    if(root->left == NULL && root->right == NULL)
                    {
                        delete root;
                        root = NULL;
                    }
                    //case2: When the node to be deleted has ONLY LEFT child
                    else if(root->right == NULL)
                    {
                        Node* temp = root;
                        root = root->left;
                        delete temp;
                    }
                    //case3: When the node to be deleted has ONLY RIGHT child
                    else if(root->left == NULL)
                    {
                        Node* temp = root;
                        root = root->right;
                        delete temp;
                    }
                    //case4: When the node to be deleted has TWO children
                    else
                    {
                        Node* maxNode = findMaxNode(root->left);//finding the maximum in LEFT sub-tree
                        root->data = maxNode->data; //Overwriting the root node with MAX-LEFT
                        root->left = DeleteNodeInBST(root->left, maxNode->data);//deleted the MAX-LEFT node
                    }
                    return root;
                }

            }

答案 4 :(得分:0)

算法:

->Find the node which need to delete (assume data is given)
->Find the deepest node of tree
->Replace deepest node's data with the node to be deleted
->Delete the deepest node

Java实现:

 public static void deleteTheNode(BTNode root, int data) {
    BTNode nodeToDelete = findTheNode(root, data);

    if (nodeToDelete == null) {
        System.out.println("Node Does not exists in Binary Tree");
        return;
    }
    BTNode deepestNode = findDepestNodeOfBinaryTree(root);
    nodeToDelete.setData(deepestNode.getData());
    _deleteTheNode(root, deepestNode);

}

private static void _deleteTheNode(BTNode root, BTNode node) {
    Queue<BTNode> q = new LinkedList<>();
    q.offer(root);

    while (!q.isEmpty()) {
        BTNode temp = q.poll();
        if (temp.getLeft() == node) {
            temp.setLeft(null);
            node = null;
            break;
        } else if (temp.getRight() == node) {
            temp.setRight(null);
            node = null;
            break;
        }
        if (temp.getLeft() != null) {
            q.offer(temp.getLeft());
        }
        if (temp.getRight() != null) {
            q.offer(temp.getRight());
        }
    }
}
//Find the deepest nodeof the binary tree
public static BTNode findDepestNodeOfBinaryTree(BTNode root) {
    int depth = 0;
    BTNode deepetNode = root;
    Stack<BTNode> nodes = new Stack<>();
    Stack<BTNode> path = new Stack<>();

    if (root == null) {
        return null;
    }
    nodes.push(root);
    while (!nodes.empty()) {
        BTNode node = nodes.peek();
        if (!path.empty() && node == path.peek()) {
            if (path.size() > depth) {
                depth = path.size() - 1;
                deepetNode = node;
            }
            path.pop();
            nodes.pop();
        } else {
            path.push(node);
            if (node.getRight() != null) {
                nodes.push(node.getRight());
            }
            if (node.getLeft() != null) {
                nodes.push(node.getLeft());
            }
        }
    }

    return deepetNode;
}

答案 5 :(得分:0)

找到要删除的节点的inorder后继。然后复制节点的inorder继承者的内容并删除inorder后继者。 (你也可以使用incessor而不是inorder继承者)

答案 6 :(得分:-1)

简单删除具有2个子节点的节点是将已删除节点的父节点子节点与其后继节点重新标记。

答案 7 :(得分:-1)

您无法使用右子树的最左侧节点。假设你有一棵树,右子树的最左边节点是15,但是15的父节点也是15,所以用右子树上最左边的节点替换要删除的节点可以给你一个相等的节点右子树中的值。在我的例子中,15将成为该子树的新根,然后在根的右边会有另外15个。