C# 红黑树插入修复错误
我有一个关于在c#中插入红黑树的作业问题。我写了下面的代码,程序在添加前3个数字时没有任何问题。当我尝试添加第四个数字时,我得到一个NullReferenceException。我花了两天时间试图解决这个错误,但我想不出来C# 红黑树插入修复错误,c#,data-structures,red-black-tree,C#,Data Structures,Red Black Tree,我有一个关于在c#中插入红黑树的作业问题。我写了下面的代码,程序在添加前3个数字时没有任何问题。当我尝试添加第四个数字时,我得到一个NullReferenceException。我花了两天时间试图解决这个错误,但我想不出来 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Algoritmalar3b { class rbtNode { publ
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);
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间算法3b
{
类rbtNode
{
公钥;
公共字符颜色;
公共RBT节点左、右、p;
公共rbtNode(int键、字符颜色、rbtNode左、rbtNode右、rbtNode p)
{
this.key=key;
这个颜色=颜色;
this.left=左;
这个。右=右;
这个,p=p;
}
}
班级计划
{
静态rbtNode Tnil=新的rbtNode(null,'B',null,null,null);
静态void Main(字符串[]参数)
{
rbtNode root=新的rbtNode(null,'B',Tnil,Tnil,null);
RB_插入(根,7);
RB_插入(根,3);
RB_插入(根,89);
RB_插入物(根,4);
RB_插入物(根,9);
RB_插入物(根,15);
RB_插入物(根,35);
RB_插入(根,8);
RB_插件(根,24);
预订单(根);
}
静态无效RB_插入件(RBT节点T,内部除气器)
{
rbtNode z=新的rbtNode(deger,null,Tnil,Tnil,null);
if(T.key==null)
T.key=deger;
其他的
{
rbtNode y=新的rbtNode(null,null,Tnil,Tnil,null);
y=Tnil;
rbtNode x=新的rbtNode(null,null,Tnil,Tnil,null);
x=T;
while(x!=Tnil)
{
y=x;
如果(z键
}您似乎在三个方面存在问题:
- RB树算法。但看起来你就快到了
- 调试。回溯这样的错误只需要2分钟,如果你是新手,可能需要2小时。但不是两天
- 问一个好问题。你有一个空参考,但在哪一行?那一行上的变量/字段值是多少
当我快速查看Fixup方法和代码的其余部分时,我怀疑您可能有一个p(Parent)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成员还为您提供了放置(条件)断点的好位置 我认为您的修复功能有点出错。在while循环中添加某些条件,即
while (z != null && z.Getparent() != null && z.Getparent().Getcolor() == 'R')
此外,您在while循环的其他部分也犯了一个重大错误。更改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);**
}
编辑:您还需要在两个旋转函数中添加更多的条件。使用调试器和一张纸(画出发生了什么和应该发生什么)逐步通过显示行为的最小树。或者,至少,表明