【问题标题】:Error in implementing a Red black Tree using a sentinel object, in Java在 Java 中使用哨兵对象实现红黑树时出错
【发布时间】:2020-12-02 17:49:00
【问题描述】:

因此,我正在尝试使用“算法简介”中所述的哨兵来实现红黑树的插入。

我为一个红黑节点创建了一个通用类,它的数据属性为类型参数,其他属性为:父(节点类型)、左子(节点类型)、右子(节点类型)和颜色(具有红色和黑色值的枚举类型)。

红背节点类:-

public class RedBlackTreeNode<T extends Comparable<T>> {

enum color{
    RED,
    BLACK
}

private T data;
private color color;
private RedBlackTreeNode<T> leftChild;
private RedBlackTreeNode<T> rightChild;
private RedBlackTreeNode<T> parent;


public RedBlackTreeNode(T data) {
    this.data = data;
    leftChild = null;
    rightChild = null;
    parent = null;
    color = null;
}


public T getData() {
    return data;
}
public void setData(T data) {
    this.data = data;
}
public color getColor() {
    return color;
}
public void setColor(color color) {
    this.color = color;
}
public RedBlackTreeNode<T> getLeftChild() {
    return leftChild;
}
public void setLeftChild(RedBlackTreeNode<T> leftChild) {
    this.leftChild = leftChild;
}
public RedBlackTreeNode<T> getRightChild() {
    return rightChild;
}
public void setRightChild(RedBlackTreeNode<T> rightChild) {
    this.rightChild = rightChild;
}
public RedBlackTreeNode<T> getParent() {
    return parent;
}
public void setParent(RedBlackTreeNode<T> parent) {
    this.parent = parent;
}

}

红黑树类:

import redBlackTree.RedBlackTreeNode.color;

public class RedBlackTree<T extends Comparable<T>> {

    private RedBlackTreeNode<T> sentinel

;
    private RedBlackTreeNode<T> root;

    public RedBlackTree() {
        sentinel = new RedBlackTreeNode<>(null);
        sentinel.setColor(color.BLACK);
        root = null;
    }

    public void redBlackInsert(RedBlackTreeNode<T> z) {

        RedBlackTreeNode<T> y, x;
        int temp;

        y = sentinel;
        x = this.root;

        //Getting NullPointerException in the below while loop condition
        while ((x.getData()) != null) {
            y = x;

            temp = z.getData().compareTo(x.getData());
            if (temp < 0) {
                x = x.getLeftChild();
            } else {
                x = x.getRightChild();
                System.out.println("Right child of X: " + x);
                System.out.println("Sentinel: " + x);
            }
        }

        z.setParent(y);

        if (y.getData() != null) {
            temp = z.getData().compareTo(y.getData());
            if (temp < 0) {
                y.setLeftChild(z);
            } else {
                y.setRightChild(z);
            }
        } else {
            root = z;
        }
        z.setLeftChild(sentinel);
        z.setRightChild(sentinel);
        z.setColor(color.RED);

        redBlackInsertFix(z);
        System.out.println("First node inserted");

    }

    private void redBlackInsertFix(RedBlackTreeNode<T> z) {
        while (z.getParent().getColor() == color.RED) {
            if (z.getParent() == z.getParent().getParent().getLeftChild()) {
                RedBlackTreeNode<T> y;
                y = z.getParent().getParent().getRightChild();
                if (y.getColor() == color.RED) {
                    z.getParent().setColor(color.BLACK);
                    y.setColor(color.BLACK);
                    z.getParent().getParent().setColor(color.RED);
                    z = z.getParent().getParent();
                } else if (z == z.getParent().getRightChild()) {
                    z = z.getParent();
                    leftRotate(z);
                }
                z.getParent().setColor(color.BLACK);
                z.getParent().getParent().setColor(color.RED);
                rightRotate(z.getParent().getParent());
            } else {
                RedBlackTreeNode<T> y;
                y = z.getParent().getParent().getLeftChild();
                if (y.getColor() == color.RED) {
                    z.getParent().setColor(color.BLACK);
                    y.setColor(color.BLACK);
                    z.getParent().getParent().setColor(color.RED);
                    z = z.getParent().getParent();
                } else if (z == z.getParent().getLeftChild()) {
                    z = z.getParent();
                    rightRotate(z);
                }
                z.getParent().setColor(color.BLACK);
                z.getParent().getParent().setColor(color.RED);
                leftRotate(z.getParent().getParent());
            }
        }
        root.setColor(color.BLACK);

    }

    private void rightRotate(RedBlackTreeNode<T> y) {

        RedBlackTreeNode<T> x;
        x = y.getLeftChild();
        y.setLeftChild(x.getRightChild());
        if (x.getRightChild() != sentinel) {
            x.getRightChild().setParent(y);
        }
        x.setParent(y.getParent());
        if (y.getParent() == sentinel) {
            root = x;
        } else if (y == y.getParent().getLeftChild()) {
            y.getParent().setLeftChild(x);
        } else {
            y.getParent().setRightChild(x);
        }
        x.setRightChild(y);
        y.setParent(x);
    }

    private void leftRotate(RedBlackTreeNode<T> x) {

        RedBlackTreeNode<T> y;
        y = x.getRightChild();
        x.setRightChild(y.getLeftChild());
        if (y.getLeftChild() != sentinel) {
            y.getLeftChild().setParent(x);
        }
        y.setParent(x.getParent());
        if (x.getParent() == sentinel) {
            root = y;
        } else if (x == x.getParent().getLeftChild()) {
            x.getParent().setLeftChild(y);
        } else {
            x.getParent().setRightChild(y);
        }
        y.setLeftChild(x);
        x.setParent(y);
    }

    public void inOrderTraversal(RedBlackTreeNode<T> x) {

        if (x.getData() != sentinel.getData()) {
            inOrderTraversal(x.getLeftChild());
            System.out.println(x.getData());
            inOrderTraversal(x.getRightChild());
        }
    }

    public RedBlackTreeNode<T> getRoot() {
        return root;
    }
}

这是具有 main 方法的类:

public class RedBlackTreeDriver {

    public static void main(String[] args) {
        
        RedBlackTreeNode<Integer> one = new RedBlackTreeNode<>(50);
        RedBlackTreeNode<Integer> two = new RedBlackTreeNode<>(55);
        RedBlackTreeNode<Integer> three = new RedBlackTreeNode<>(48);
        
        RedBlackTree<Integer> rbt = new RedBlackTree<>();
        
        //System.out.println(rbt.getRoot());
        
        //NullPointerException
        rbt.redBlackInsert(one);
        
        System.out.println("ROOT: "+ rbt.getRoot());
        
        rbt.redBlackInsert(two); 
        rbt.redBlackInsert(three);
    
        System.out.println(rbt.getRoot());
        
        rbt.inOrderTraversal(rbt.getRoot());
    }

}

在插入每个具有值的节点后,我正在尝试添加一个哨兵节点(将数据属性设置为“null”)。所以,在添加第一个节点之后,我应该能够沿着树(寻找哨兵)并将新节点添加到哨兵的父节点。

我在 Red Black Tree 类中遇到空指针异常。 到目前为止,我已经尝试了我所知道的几乎所有东西。 有人可以指导我吗?

【问题讨论】:

    标签: java algorithm data-structures red-black-tree clrs


    【解决方案1】:

    好的,经过一番思考,我到了这一点,我第一次确定,当我们插入一个节点时,它不应该检查 while 循环条件。
    这就是红黑树类的变化:

    package redBlackTree;
    
    import redBlackTree.RedBlackTreeNode.color;
    
    public class RedBlackTree<T extends Comparable<T>> {
    
        private RedBlackTreeNode<T> sentinel;
        private RedBlackTreeNode<T> root;
    
        public RedBlackTree() {
            sentinel = new RedBlackTreeNode<>(null);
            sentinel.setColor(color.BLACK);
            root = null;
        }
    
        public void redBlackInsert(RedBlackTreeNode<T> z) {
    
            RedBlackTreeNode<T> y, x;
            int temp;
    
            y = sentinel;
            x = this.root;
    
            System.out.println(x);
    
            // Getting NullPointerException in the below while loop condition
            if (x != null) {
                while (x.getData() != null) {
                    y = x;
    
                    temp = z.getData().compareTo(x.getData());
                    if (temp < 0) {
                        x = x.getLeftChild();
                    } else {
                        x = x.getRightChild();
                        System.out.println("Right child of X: " + x);
                        System.out.println("Sentinel: " + sentinel);
                    }
                }
            }
            z.setParent(y);
    
            if (y.getData() != null) {
                temp = z.getData().compareTo(y.getData());
                if (temp < 0) {
                    y.setLeftChild(z);
                } else {
                    y.setRightChild(z);
                }
            } else {
                root = z;
            }
            z.setLeftChild(sentinel);
            z.setRightChild(sentinel);
            z.setColor(color.RED);
    
            redBlackInsertFix(z);
            System.out.println("First node inserted");
    
        }
    
        private void redBlackInsertFix(RedBlackTreeNode<T> z) {
            while (z.getParent().getColor() == color.RED) {
                if (z.getParent() == z.getParent().getParent().getLeftChild()) {
                    RedBlackTreeNode<T> y;
                    y = z.getParent().getParent().getRightChild();
                    if (y.getColor() == color.RED) {
                        z.getParent().setColor(color.BLACK);
                        y.setColor(color.BLACK);
                        z.getParent().getParent().setColor(color.RED);
                        z = z.getParent().getParent();
                    } else if (z == z.getParent().getRightChild()) {
                        z = z.getParent();
                        leftRotate(z);
                    }
                    z.getParent().setColor(color.BLACK);
                    z.getParent().getParent().setColor(color.RED);
                    rightRotate(z.getParent().getParent());
                } else {
                    RedBlackTreeNode<T> y;
                    y = z.getParent().getParent().getLeftChild();
                    if (y.getColor() == color.RED) {
                        z.getParent().setColor(color.BLACK);
                        y.setColor(color.BLACK);
                        z.getParent().getParent().setColor(color.RED);
                        z = z.getParent().getParent();
                    } else if (z == z.getParent().getLeftChild()) {
                        z = z.getParent();
                        rightRotate(z);
                    }
                    z.getParent().setColor(color.BLACK);
                    z.getParent().getParent().setColor(color.RED);
                    leftRotate(z.getParent().getParent());
                }
            }
            root.setColor(color.BLACK);
    
        }
    
        private void rightRotate(RedBlackTreeNode<T> y) {
    
            RedBlackTreeNode<T> x;
            x = y.getLeftChild();
            y.setLeftChild(x.getRightChild());
            if (x.getRightChild() != sentinel) {
                x.getRightChild().setParent(y);
            }
            x.setParent(y.getParent());
            if (y.getParent() == sentinel) {
                root = x;
            } else if (y == y.getParent().getLeftChild()) {
                y.getParent().setLeftChild(x);
            } else {
                y.getParent().setRightChild(x);
            }
            x.setRightChild(y);
            y.setParent(x);
        }
    
        private void leftRotate(RedBlackTreeNode<T> x) {
    
            RedBlackTreeNode<T> y;
            y = x.getRightChild();
            x.setRightChild(y.getLeftChild());
            if (y.getLeftChild() != sentinel) {
                y.getLeftChild().setParent(x);
            }
            y.setParent(x.getParent());
            if (x.getParent() == sentinel) {
                root = y;
            } else if (x == x.getParent().getLeftChild()) {
                x.getParent().setLeftChild(y);
            } else {
                x.getParent().setRightChild(y);
            }
            y.setLeftChild(x);
            x.setParent(y);
        }
    
        public void inOrderTraversal(RedBlackTreeNode<T> x) {
    
            if (x.getData() != sentinel.getData()) {
                inOrderTraversal(x.getLeftChild());
                System.out.println(x.getData());
                inOrderTraversal(x.getRightChild());
            }
        }
    
        public RedBlackTreeNode<T> getRoot() {
            return root;
        }
    }
    

    我希望这不是一个非常幼稚的问题。

    【讨论】:

      猜你喜欢
      • 2014-09-23
      • 2015-05-18
      • 2018-06-17
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-14
      相关资源
      最近更新 更多