Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中二叉树节点删除的问题_Java_Data Structures_Binary Search Tree - Fatal编程技术网

Java中二叉树节点删除的问题

Java中二叉树节点删除的问题,java,data-structures,binary-search-tree,Java,Data Structures,Binary Search Tree,我想尝试并实现我自己的BST作为练习,但我在节点移除方面遇到了困难。我不明白为什么它在某些情况下不起作用。我从一本书中得到了这个算法,但当我用随机元素测试它时,有些情况下它不会删除元素,甚至会打乱它们的顺序,因此它们不再被排序。我做错了什么?有什么更好的方法来实现这一点 注意:方法中的所有println()语句仅用于调试目的 class TreeNode<T extends Comparable<T>> { T data; TreeNode<T>

我想尝试并实现我自己的BST作为练习,但我在节点移除方面遇到了困难。我不明白为什么它在某些情况下不起作用。我从一本书中得到了这个算法,但当我用随机元素测试它时,有些情况下它不会删除元素,甚至会打乱它们的顺序,因此它们不再被排序。我做错了什么?有什么更好的方法来实现这一点

注意:方法中的所有println()语句仅用于调试目的

class TreeNode<T extends Comparable<T>> {
    T data;
    TreeNode<T> left;
    TreeNode<T> right;
    TreeNode<T> parent;

    TreeNode(T data) {
        this.data = data;
    }

    boolean hasBothChildren() {
        return hasLeftChild() && hasRightChild();
    }

    boolean hasChildren() {
        return hasLeftChild() || hasRightChild();
    }

    boolean hasLeftChild() {
        return left != null;
    }

    boolean hasRightChild() {
        return right != null;
    }

    boolean isLeftChild() {
        return this.parent.left == this;
    }

    boolean isRightChild() {
        return this.parent.right == this;
    }
}

public class BinaryTreeSet<T extends Comparable<T>> {
    private TreeNode<T> root;

    private void makeRoot(T element) {
        TreeNode<T> node = new TreeNode<T>(element);
        root = node;
    }

    private TreeNode<T> find(T element) {
        TreeNode<T> marker = root;
        TreeNode<T> found = null;

        while (found == null && marker != null) {
            int comparator = (marker.data.compareTo(element));

            if (comparator > 0)
                marker = marker.left;
            else if (comparator < 0)
                marker = marker.right;
            else
                found = marker;
        }

        return found;
    }

    private TreeNode<T> max(TreeNode<T> root) {
        TreeNode<T> currentMax = root;

        while (currentMax.hasRightChild()) {
            currentMax = currentMax.right;
        }

        return currentMax;
    }

    // returns the inorder predecessor of node
    private TreeNode<T> predecessor(TreeNode<T> node) {
        return max(node.left);
    }

    // removes a given node with 0 or 1 children
    private void removeNode(TreeNode<T> node) {
        if (!node.hasChildren()) {
            System.out.println("node with no children");
            if (node.isLeftChild())
                node.parent.left = null;
            else
                node.parent.right = null;
        }
        else {
            System.out.println("node with 1 child");
            if (node.isRightChild()) {
                if (node.hasLeftChild())
                    node.parent.right = node.left;
                else if (node.hasRightChild())
                    node.parent.right = node.right;
            }
            else if (node.isLeftChild()) {
                if (node.hasLeftChild())
                    node.parent.left = node.left;
                else if (node.hasRightChild())
                    node.parent.left = node.right;
            }
        }

        node = null;
    }

    public BinaryTreeSet() {
        root = null;
    }

    public void addElement(T element) {
        if (root == null)
            makeRoot(element);
        else {
            TreeNode<T> marker = root;
            TreeNode<T> node = new TreeNode<T>(element);
            boolean done = false;

            while(!done) {
                int comparator = marker.data.compareTo(element);
                if (comparator > 0) {
                    if (marker.hasLeftChild())
                        marker = marker.left;
                    else {
                        marker.left = node;
                        done = true;
                    }
                }
                else if (comparator < 0) {
                    if (marker.hasRightChild())
                        marker = marker.right;
                    else {
                        marker.right = node;
                        done = true;
                    }
                }
                else
                    return;

                node.parent = marker;
            }
        }
    }

    public boolean contains(T element) {
        boolean found = (find(element) == null)? false : true;
        return found;
    }

    public boolean removeElement(T element) {
        TreeNode<T> node = find(element);
        if (node == null)
            return false;

        // removal of a node with no children
        if (!node.hasChildren()) {
            if (node.isLeftChild()) {
                node.parent.left = null;
            }
            else if (node.isRightChild()) {
                node.parent.right = null;
            }
        }

        // removal of a node with both children
        else if (node.hasBothChildren()) {
            TreeNode<T> pred = predecessor(node);
            T temp = pred.data;
            pred.data = node.data;
            node.data = temp;
            removeNode(pred);
        }

        // removal of a node with only 1 child
        else {
            if (node.isRightChild()) {
                if (node.hasLeftChild())
                    node.parent.right = node.left;
                else if (node.hasRightChild())
                    node.parent.right = node.right;
            }
            else if (node.isLeftChild()) {
                if (node.hasLeftChild())
                    node.parent.left = node.left;
                else if (node.hasRightChild())
                    node.parent.left = node.right;
            }

        }

        node = null;
        System.out.println("item removed: " + !contains(element));
        return true;
    }
}
类树节点{
T数据;
左树突;
特雷诺德右翼;
树状体亲本;
树节点(T数据){
这个数据=数据;
}
布尔hasBothChildren(){
返回hasLeftChild()&&hasRightChild();
}
布尔hasChildren(){
返回hasLeftChild()| | hasRightChild();
}
布尔hasleeftchild(){
返回左!=null;
}
布尔hasRightChild(){
返回右侧!=null;
}
布尔值isLeftChild(){
返回this.parent.left==this;
}
布尔isRightChild(){
返回this.parent.right==this;
}
}
公共类二进制树集{
独活根;
私有void makeRoot(T元素){
TreeNode=新的TreeNode(元素);
根=节点;
}
私有树节点查找(T元素){
TreeNode标记=根;
TreeNode found=null;
while(found==null&&marker!=null){
int comparator=(marker.data.compareTo(element));
如果(比较器>0)
marker=marker.left;
否则如果(比较器<0)
marker=marker.right;
其他的
发现=标记;
}
发现退货;
}
私有树节点最大值(树节点根){
TreeNode currentMax=根;
while(currentMax.hasRightChild()){
currentMax=currentMax.right;
}
返回电流最大值;
}
//返回节点的顺序前置项
专用TreeNode前置节点(TreeNode节点){
返回最大值(节点左侧);
}
//删除具有0或1个子节点的给定节点
私有void removeNode(TreeNode节点){
如果(!node.hasChildren()){
System.out.println(“没有子节点的节点”);
if(node.isLeftChild())
node.parent.left=null;
其他的
node.parent.right=null;
}
否则{
System.out.println(“具有1个子节点的节点”);
if(node.isRightChild()){
if(node.hasleeftchild())
node.parent.right=node.left;
else if(node.hasRightChild())
node.parent.right=node.right;
}
else if(node.isLeftChild()){
if(node.hasleeftchild())
node.parent.left=node.left;
else if(node.hasRightChild())
node.parent.left=node.right;
}
}
node=null;
}
公共二进制树集(){
root=null;
}
公共无效附加元素(T元素){
if(root==null)
makeRoot(元素);
否则{
TreeNode标记=根;
TreeNode=新的TreeNode(元素);
布尔完成=假;
而(!完成){
int comparator=marker.data.compareTo(元素);
如果(比较器>0){
if(marker.hasleeftchild())
marker=marker.left;
否则{
marker.left=节点;
完成=正确;
}
}
否则如果(比较器<0){
if(marker.hasRightChild())
marker=marker.right;
否则{
marker.right=节点;
完成=正确;
}
}
其他的
返回;
node.parent=标记;
}
}
}
公共布尔包含(T元素){
布尔值find=(find(element)==null)?false:true;
发现退货;
}
公共布尔removeElement(T元素){
树节点=查找(元素);
if(node==null)
返回false;
//删除没有子节点的节点
如果(!node.hasChildren()){
if(node.isLeftChild()){
node.parent.left=null;
}
else if(node.isRightChild()){
node.parent.right=null;
}
}
//删除包含两个子节点的节点
else if(node.hasBothChildren()){
TreeNode pred=前置节点(node);
温度=预测数据;
pred.data=node.data;
node.data=temp;
removeNode(pred);
}
//删除只有一个子节点的节点
否则{
if(node.isRightChild()){
if(node.hasleeftchild())
node.parent.right=node.left;
else if(node.hasRightChild())
node.parent.right=node.right;
}
else if(node.isLeftChild()){
if(node.hasleeftchild())
node.parent.left=node.left;
else if(node.hasRightChild())
node.parent.left=node.right;
}
}
node=null;
System.out.println(“删除项:+!包含(元素));
返回true;
}
}

找到了让我头疼的bug。问题出现在我删除具有0或1个子节点的节点的情况下。我没有更新它们的父节点,所以这会把代码搞乱。所以,而不是比如说,

if (node.hasLeftChild())
    node.parent.right = node.left;
我应该写信的

if (node.hasLeftChild()) {
    node.parent.left = node.left;
    node.left.parent = node.parent;
}
在任何情况下,我都会和一个独生子女打交道。另外,我忘记了更新根,因为根是
 boolean rootOncePrint = true;
    public void printAllTree(TreeNode<T> startNode){
        if(startNode == null) return;
        //System.out.println(startNode.data);
        if(rootOncePrint){
            System.out.println("Root : " + startNode.data);
            rootOncePrint = false;
        }

        if(startNode.hasChildren()){
            if(startNode.hasLeftChild()){
                printAllTree(startNode.left);
            } 
            if(startNode.hasRightChild()){
                printAllTree(startNode.right);
            }

        }
        if(startNode != root){
            T parentValue = startNode.parent.data;
            T dataValue = startNode.data; 
            System.out.println(startNode.data + ((parentValue.compareTo(dataValue) > 0)?"L":"R"));
        }

    }