我有一个关于在c#中插入红黑树的作业问题。我编写了下面的代码,程序在添加前3个数字时没有任何问题。当我尝试添加第4个数字时,我得到一个NullReferenceException。我试图解决错误2天,但我无法弄明白。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Algoritmalar3b
{
class rbtNode
{
public int? key;
public char? color;
public rbtNode left, right, p;
public rbtNode(int? key, char? color, rbtNode left, rbtNode right, rbtNode p)
{
this.key = key;
this.color = color;
this.left = left;
this.right = right;
this.p = p;
}
}
class Program
{
static rbtNode Tnil = new rbtNode(null, 'B', null, null, null);
static void Main(string[] args)
{
rbtNode root = new rbtNode(null, 'B', Tnil, Tnil, null);
RB_Insert(root, 7);
RB_Insert(root, 3);
RB_Insert(root, 89);
RB_Insert(root, 4);
RB_Insert(root, 9);
RB_Insert(root, 15);
RB_Insert(root, 35);
RB_Insert(root, 8);
RB_Insert(root, 24);
preOrderWalk(root);
}
static void RB_Insert(rbtNode T, int? deger)
{
rbtNode z = new rbtNode(deger, null, Tnil, Tnil, null);
if (T.key == null)
T.key = deger;
else
{
rbtNode y = new rbtNode(null, null, Tnil, Tnil, null);
y = Tnil;
rbtNode x = new rbtNode(null, null, Tnil, Tnil, null);
x = T;
while (x != Tnil)
{
y = x;
if (z.key < x.key)
x = x.left;
else
x = x.right;
}
z.p = y;
if (y == Tnil)
T = z;
else if (z.key < y.key)
y.left = z;
else
y.right = z;
z.left = Tnil;
z.right = Tnil;
z.color = 'R';
RB_Insert_Fixup(T, z);
}
}
static void RB_Insert_Fixup(rbtNode T, rbtNode z)
{
rbtNode y = new rbtNode(null, null, Tnil, Tnil, null);
while (z.p.color == 'R')
{
if (z.p == z.p.p.left)
{
y = z.p.p.right;
if (y.color == 'R')
{
z.p.color = 'B';
y.color = 'B';
z.p.p.color = 'R';
z = z.p.p;
}
else if (z == z.p.right)
{
z = z.p;
Left_Rotate(T, z);
z.p.color = 'B';
z.p.p.color = 'R';
Right_Rotate(T, z.p.p);
}
}
else
{
y = z.p.p.left;
if (y.color == 'R')
{
z.p.color = 'B';
y.color = 'B';
z.p.p.color = 'R';
z = z.p.p;
}
else if (z == z.p.left)
{
z = z.p;
Left_Rotate(T, z);
z.p.color = 'B';
z.p.p.color = 'R';
Right_Rotate(T, z.p.p);
}
}
}
T.color = 'B';
}
static void Left_Rotate(rbtNode T, rbtNode x)
{
rbtNode y = new rbtNode(null, null, Tnil, Tnil, null);
y = x.right;
x.right = y.left;
if (y.left != Tnil)
y.left.p = x;
y.p = x.p;
if (x.p == Tnil)
T = y;
else if (x == x.p.left)
x.p.left = y;
else
x.p.right = y;
y.left = x;
x.p = y;
}
static void Right_Rotate(rbtNode T, rbtNode x)
{
rbtNode y = new rbtNode(null, null, Tnil, Tnil, null);
y = x.left;
x.left = y.right;
if (y.right != null)
y.right.p = x;
y.p = x.p;
if (x.p == null)
T = y;
else if (x == x.p.right)
x.p.right = y;
else
x.p.left = y;
y.right = x;
x.p = y;
}
static void preOrderWalk(rbtNode T)
{
if (T.color == 'B')
Console.WriteLine("-{0}", T.key);
else
Console.WriteLine("{0}", T.key);
if (T.left != null)
preOrderWalk(T.left);
if (T.right != null)
preOrderWalk(T.right);
}
}
}
答案 0 :(得分:2)
看来你在3个方面遇到了问题:
当我快速查看Fixup方法和其余代码时,我怀疑你可能在错误的点上有一个p(父)ref为null。
作为诊断工具,更改常规属性中的.p成员:
class rbtNode
{
private rbtNode _parent;
public rbtNode Parent
{
get { return _parent; }
set
{
System.Diagnostics.Debug.Assert(value != null);
_parent = value;
}
}
....
我认为你必须允许_parent = null但仅限于构造函数。
get / set成员还为您提供放置(条件)断点的好位置。
答案 1 :(得分:0)
我相信你的 fix_up 功能有点不对劲。在while循环中添加某些条件,即
while (z != null && z.Getparent() != null && z.Getparent().Getcolor() == 'R')
另外,你在while循环的else部分犯了一个重大错误。更改LeftRotate和RightRotate函数的顺序,应如下所示:
else if (z == z.Getparent().Getleft())
{
z = z.Getparent();
**RightRotate(T, z);**
z.Getparent().Setcolor('B');
z.Getparent().Getparent().Setcolor('R');
**LeftRotate(T, z);**
}
编辑:您还需要在两个旋转功能中添加更多条件。