我正在尝试在C#中实现一个红黑树。我已经创建了一个名为sRbTreeNode的对象,它有一个String键,Color,Left,Right和Parent属性。 我成功地管理了Insert,InsertFixUp,LeftRotate,RightRotate,Delete等方法的实现,现在我遇到了DeleteFixUp方法的问题。
DeleteFixUp负责在删除后再次平衡树(使用旋转和更改节点颜色)。
我尝试使用名为“算法简介”的书中的伪代码实现该方法。
这是我的代码:
private static void DeleteFixup(ref sRbTreeNode root, sRbTreeNode x)
{
sRbTreeNode y;
while (x != root && x.Color == BLACK)
{
if (x == x.Parent.Left) // determine sub tree from parent
{
y = x.Parent.Right; // y is x's sibling
if (y.Color == RED)
{ // x is black, y is red - make both black and rotate
y.Color = BLACK;
x.Parent.Color = RED;
LeftRotate(ref root, x.Parent);
y = x.Parent.Right;
}
if (y.Left.Color == BLACK &&
y.Right.Color == BLACK)
{ // children are both black
y.Color = RED; // change parent to red
x = x.Parent; // move up the tree
}
else
{
if (y.Right.Color == BLACK)
{
y.Left.Color = BLACK;
y.Color = RED;
RightRotate(ref root, y);
y = x.Parent.Right;
}
y.Color = x.Parent.Color;
x.Parent.Color = BLACK;
y.Right.Color = BLACK;
LeftRotate(ref root, x.Parent);
x = root;
}
}
else
{ // right subtree - same as code above with right and left swapped
y = x.Parent.Left;
if (y.Color == RED)
{
y.Color = BLACK;
x.Parent.Color = RED;
RightRotate(ref root, x.Parent);
y = x.Parent.Left;
}
if (y.Right.Color == BLACK &&
y.Left.Color == BLACK)
{
y.Color = RED;
x = x.Parent;
}
else
{
if (y.Left.Color == BLACK)
{
y.Right.Color = BLACK;
y.Color = RED;
LeftRotate(ref root, y);
y = x.Parent.Left;
}
y.Color = x.Parent.Color;
x.Parent.Color = BLACK;
y.Left.Color = BLACK;
RightRotate(ref root, x.Parent);
x = root;
}
}
}
x.Color = BLACK;
}
我每次都在不同的地方继续遇到错误“对象引用未设置为对象的实例”...
我在互联网上搜索了这个的实现,刚刚在CodeProject上发现了一篇文章,它完全像我一样实现了它。我试着复制他们的代码,希望我用眼睛遗漏一些东西,但它既不起作用......
在我开始撕掉我的头发之前,有人可以帮助我!! ...? :)
答案 0 :(得分:1)
虽然可能不是您问题的直接答案,但只需逐步调试调试器中的代码,即可学习。 Plus 你可能会自己解决这个问题!如果您需要帮助设置断点,检查变量或踩踏,请告诉我。 Visual Studio很容易使用它几乎已经死了。
答案 1 :(得分:1)
经过一番研究,我发现问题出在我处理我建造的红黑树的方式上。
根据有关该主题的书籍(包括我正在学习的那本书!),您应该让树底部的每个节点都指向“空节点”。空节点是没有值且颜色为黑色的节点。我以为我不必在我的树上实现空节点,并且在每个检查黑色节点的地方,我都添加了“|| node == null”,因为它可能正在检查空节点。 问题是有时您需要检查空节点的父节点,如果您实际上没有实现“空节点”,那么在尝试访问它的父属性时会出现错误。
我通过向没有子节点的每个节点添加一个空值和黑色着色的节点来实现“空节点”。它需要对树上的大多数操作方法进行一些调整,但最终它解决了(几乎)我的所有问题。
感谢大家帮助我! :)
答案 2 :(得分:0)
在某处有空参数滑落。
如果x == null
,我们会在测试if
后立即崩溃。
如果x.Parent
的任何一个孩子都为空,我们也会崩溃。
您需要测试这些空条件并正确处理它们。
答案 3 :(得分:0)
让我们看看......
while (x != root && (x == null || x.Color == BLACK))
{
if (x == x.Parent.Left) // determine sub tree from parent
因此,如果x在开始时为null,则尝试取消引用x.Parent,这将引发您获得的异常。我看了两行,发现了一个bug。
您需要在解除引用之前的某个时刻检查每个引用是否为null。