简体   繁体   English

Java二进制搜索树

[英]java binary search tree

I have a question about how would I remove a child from a node (root)? 我对如何从节点(根)删除孩子有疑问? Since I can't call remove, if I make the child null, will the children of that child move up? 由于无法调用remove,因此如果我将孩子设为空,那么该孩子的孩子会向上移动吗? Like, would I just initialize it as null?? 就像,我将其初始化为null吗? Or would I point to the child's child? 还是我要指出孩子的孩子?

In a traditional binary search tree, removal of a node can have different consequences depending on how many children the node has: 在传统的二叉搜索树中,删除节点可能会产生不同的结果,具体取决于节点具有多少个子节点:

  • A node with no children can simply be removed 没有孩子的节点可以简单地删除
  • A node with one child can be removed, and the node will be replaced by its only child. 可以删除具有一个子节点的节点,并将该节点替换为其唯一的子节点。 This applies regardless of whether the child is a left or right child. 无论孩子是左还是右孩子,这都适用。
  • A node with two children has a slightly more complicated rule: you must find the in-order successor or in-order predecessor of the node to be removed, replace the current node's value with its sucessor's or predecessor's value, then delete the successor or predecessor (according to these rules). 具有两个子节点的节点的规则稍微复杂一些:您必须找到要删除的节点的有序后继者有序前任者,用其后继者或前任者的值替换当前节点的值,然后删除后继者或前任者的值(根据这些规则)。

Is this homework? 这是作业吗? Nothing wrong with that... we just like to help people learn rather than tell them the answers. 没错...我们只是想帮助人们学习而不是告诉他们答案。

If you just set the child node to null you'll lose any information about the childs children. 如果仅将子节点设置为null,则将丢失有关子节点的所有信息。

A standard tree class will know its children, usually stuck in an array or Collection - in the case of a binary tree, you've only got two direct children, so a fixed sized array will work. 标准的树类会知道其子级,通常会卡在数组或Collection中-对于二叉树,您只有两个直接的子级,因此固定大小的数组将起作用。 Because of that, they usually implement some sort of "removeMe" method that the child calls to get removed from that list of children. 因此,它们通常实现子级调用的某种“ removeMe”方法,以从该子级列表中将其删除。

As mentioned above, this gets complicated if the child you are removing has children. 如上所述,如果您要删除的孩子有孩子,这将变得很复杂。

Tim's answer seems best. 蒂姆的答案似乎最好。 But yes you will want to do one of three things depending on what kind of child it is your removing. 但是,是的,您将要根据要移除的孩子类型执行三件事之一。 If you make a child null, the children of it will not move up because you've lost reference to them. 如果您将一个孩子设为空,则该孩子的孩子将不会上移,因为您失去了对其的引用。 Instead, you'll want to determine if the left or right children of the child your removing should be set to the pointer pointing to the child your removing. 相反,您将要确定是否应该将要删除的孩子的左孩子或右孩子设置为指向您要删除的孩子的指针。 After you set the previous' nodes pointer (left or right) to the child (left or right) of the node your removing, you wont have a reference anymore to that node, so theres no need to set it to null (you can't access it anymore. Unless you wrote some sort of doubly-linked BST, in which case that's not the classic BST) 在将先前的节点指针(左或右)设置为要删除的节点的子节点(左或右)之后,您将不再有对该节点的引用,因此无需将其设置为null(您可以不再访问它。除非您编写了某种双向链接的BST,在这种情况下,这不是经典的BST。

You can do something like this (pseudo code): 您可以执行以下操作(伪代码):

Given a the root of the tree "root" and the node to delete or some data "x" do the following 给定树的根“ root”和要删除的节点或某些数据“ x”,请执行以下操作

 if x < root
      recurse to left child
 if x > root
      recurse to right child
 else //node found
      find the min item of the node right child //min item should be left most leaf node node
      replace the value of the node you want to delete with min nodes value
      now delete the min node
 return root;

code: 码:

delete(Node root, Object x){
    if(root == null){
        return null;
    }

    if(data < root.data){
        root = delete(root.left);
    }else if(root.data < data){
        root = delete(root.right);
    }else{
        if(root.left != null && root.right != null){
            Object tmp = findMin(root.right);
            root.data = tmp;
            root.right = delete(root.right, tmp);
        }else{
            return (root.left != null) ? root.left : root.right;    
        }
    }
return root;

} }

This code should help you 此代码应为您提供帮助

public Node<T> getParentOf(Node<T> child){
    findParentOf(this.root, child);
    return temp;
}

private void findParentOf(Node<T> ROOT, Node<T> child){
    if(ROOT.hasLeft()){
        findParentOf(ROOT.left, child);
    }

    if(ROOT.left == child || root.right == child){
        temp = ROOT;
    }

    if(ROOT.hasRight()){
        findParentOf(ROOT.right, child);
    }
}


private void replaceNode(Node<T> original, Node<T> newNode){
    Node<T> tempParent = getParentOf(original);
    if(original == tempParent.left){
        tempParent.left = newNode;
    }else if(original == tempParent.right){
        tempParent.right = newNode;
    }
}

private void traverseChildrenAndAdd(Node<T> newParent, Node<T> oldParent){
    newParent.insert(oldParent.data);
    if(oldParent.hasLeft()){
        traverseChildrenAndAdd(newParent,oldParent.left);
    }



    if(oldParent.hasRight()){
        traverseChildrenAndAdd(newParent,oldParent.right);
    }
}
private void deleteNode(Node<T> ROOT, Node<T> d){
    if(d.data.compareTo(ROOT.data) < 0){
        deleteNode(ROOT.left, d);
    }else if(d.data.compareTo(ROOT.data) > 0){
        deleteNode(ROOT.right, d);
    }else if(d == this.root){
        if(this.root.hasLeft()){
            traverseChildrenAndAdd(root.left, root.right);
            root = root.left;
        }else if(root.hasRight()){
            root = root.right;
        }else{
            root = null;
        }
    }else{
        if(ROOT.hasLeft()&&ROOT.hasRight()){
            Node<T> successor = getMinNode(ROOT);
            replaceNode(successor, successor.right);
        }else if(ROOT.hasLeft() || ROOT.hasRight()){
            if(ROOT.hasLeft()){
                replaceNode(ROOT, ROOT.left);
            }else{
                replaceNode(ROOT, ROOT.right);
            }
        }else{
            replaceNode(ROOT, null);
        }
    }
}

public void remove(T data){
    deleteNode(this.root, new Node<T>(data));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM