红黑树实施中的空指针

时间:2016-09-30 00:08:45

标签: java algorithm nullpointerexception red-black-tree

我有一个红色黑树实现,我使用CLRS中的伪代码实现,并且我在插入修复过程中遇到了NPE。这是我在java中的实现。 (忽略变量名称,我知道它不是惯例)

private RbtNode root;
    private RbtNode nil;
    private static final boolean BLACK = true;
    private static final boolean RED = false;

    public RedBlackTreeImpl() {
        nil = new RbtNode("");
        nil.color = BLACK;
        root = nil;
    }

    @Override
    public void rbInsert(T data) {
        RbtNode z = new RbtNode(data);
        RbtNode y = this.nil;
        RbtNode x = this.root;
        while(x != this.nil){
            y = x;
            if(z.data.toString().compareTo(x.data.toString()) < 0){
                x = x.left;
            } else {
                x = x.right;
            }
        }
        z.parent = y;
        if(y == this.nil) {
            this.root = z;
        } else {
            y.right = z;
        }
        z.left = this.nil;
        z.right = this.nil;
        z.color = RED;
        rbInsertFixup(z);
    }

    @Override
    public void rbInsertFixup(RbtNode z) {
        while(z.parent.color == RED){
            if(z.parent == z.parent.parent.left){
                RbtNode y = z.parent.parent.right;
                if(y.color == RED){
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if(z == z.parent.right){
                    z = z.parent;
                    leftRotate(z.parent.parent);
                }
                z.parent.color = BLACK;
                z.parent.parent.color = RED;
                rightRotate(z.parent.parent);
            } else {
                RbtNode y = z.parent.parent.left;
                if(y.color == RED){
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if(z == z.parent.left){
                    z = z.parent;
                    rightRotate(z.parent.parent);
                }
                z.parent.color = BLACK;
                z.parent.parent.color = RED;
                leftRotate(z.parent.parent);
            }
        }
        this.root.color = BLACK;
    }

    @Override
    public void leftRotate(RbtNode x) {
        RbtNode y = x.right;
        x.right = y.left;
        if(y.left != this.nil) {
            y.left.parent = x;
        }
        y.parent = x.parent;
        if(x.parent == this.nil){
            this.root = y;
        } else if(x == x.parent.left){
            x.parent.left = y;
        } else {
            x.parent.right = y;
        }
        y.left = x;
        x.parent = y;
    }

    @Override
    public void rightRotate(RbtNode x) {
        RbtNode y = x.left;
        x.left = y.right;
        if(y.right != this.nil) {
            y.right.parent = x;
        }
        y.parent = x.parent;
        if(x.parent == this.nil){
            this.root = y;
        } else if(x == x.parent.right){
            x.parent.right = y;
        } else {
            x.parent.left = y;
        }
        y.right = x;
        x.parent = y;
    }

节点类

public class RbtNode<T> {

    T data;
    boolean color;                  //true indicates black; false indicates red
    RbtNode<T> left;
    RbtNode<T> right, parent;

    public RbtNode(T data) {
        if (data == null) {
            throw new IllegalArgumentException("Data cannot be null");
        }
        this.data = data;
    }

    public boolean getColor() {
        return this.color;
    }

    public T getData() {
        return this.data;
    }

    public RbtNode<T> left() {
        return left;
    }

    public RbtNode<T> right() {
        return right;
    }

    public RbtNode<T> parent() {
        return parent;
    }

}

如果像上面那样运行测试插入:

       RedBlackTreeImpl rbt = new RedBlackTreeImpl();
       rbt.rbInsert("a");
       rbt.rbInsert("k");
       rbt.rbInsert("q");
       rbt.rbInsert("c");
       rbt.rbInsert("j");
       rbt.rbInsert("e");

尝试插入"c"时会发生NPE。具体地位于rbInsertFixup的{​​{1}}位于z.parent.parent.color = RED;的{​​{1}}的{​​{1}}之前的rightRotate内。在该实例中if 1}}是while,因此z的父级是root,所以它试图获得root的父级实际上是nil

我尝试使nil的左,右和父节点等于nil,但这会导致无限循环。我认为这归结为缺乏概念问题。所以我想我的问题可以分解成一个或两个问题。 我是否已经获得NPE标志,我应该继续这个过程,或者我是否设置了nil?我错过了什么?

0 个答案:

没有答案