红黑树插入修复错误

发布于 2024-11-04 20:52:24 字数 4475 浏览 0 评论 0原文

我有一个关于在 C# 中插入红黑树的家庭作业问题。我编写了下面的代码,程序在添加前 3 个数字时没有任何问题。当我尝试添加第四个数字时,出现 NullReferenceException。我试图解决这个错误两天,但我无法弄清楚。

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);
    }
}

}

I have a homework problem about inserting into red-black trees in c#. I wrote the code below and the program works without any problems for adding first 3 numbers. When I try to add the 4th number, I get a NullReferenceException. I'm trying to solve the error for 2 days but I can't figure it out.

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);
    }
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迷荒 2024-11-11 20:52:24

看来你在 3 个方面有问题:

  • RB 树算法。但看起来你已经差不多
  • 可以调试了。回溯此类错误只需 2 分钟,如果您是新手,则可能需要 2 小时。但不是2天。
  • 问一个好问题。你有一个 nullref,但是在哪一行?该行上的变量/字段的值是什么?

当我快速查看 Fixup 方法和其余代码时,我怀疑您可能在错误的位置将 ap(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 成员还为您提供了放置(条件)断点的好位置。

It seems you have problems in 3 areas:

  • The RB tree algorithm. But it looks like you're almost there
  • Debugging. It should only take 2 minutes to backtrack an error like this, maybe 2 hours if you're new. But not 2 days.
  • Asking a good question. You have a nullref, but on what line? and what are the values of the vars/fields on that line?

When I take a quick look at the Fixup method and the rest of the code I suspect you may have a p (Parent) ref being null at the wrong point.

As a diagnosis tool, change the .p member in a regular property:

class rbtNode
{    
    private rbtNode _parent;

    public rbtNode Parent
    {
         get { return _parent; }
         set
         {
             System.Diagnostics.Debug.Assert(value != null);
             _parent = value;
         }
    }
    ....

I think you will have to allow _parent=null but only in the constructor.

The get/set members also give you a good spot to place (conditional) breakpoints.

月亮邮递员 2024-11-11 20:52:24

我相信您的 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);**
                    }

编辑:您还需要在两个 Rotate 函数中添加更多条件。

I believe you are going a bit wrong in your fix_up function. Add certain conditions in while loop i.e.

while (z != null && z.Getparent() != null && z.Getparent().Getcolor() == 'R')

Also, you are making a major mistake in the else part of your while loop. Change the order of LeftRotate and RightRotate functions, it should be as follows:

               else if (z == z.Getparent().Getleft())
                    {
                        z = z.Getparent();
                        **RightRotate(T, z);**
                        z.Getparent().Setcolor('B');
                        z.Getparent().Getparent().Setcolor('R');
                        **LeftRotate(T, z);**
                    }

EDIT: you would also need to add a few more conditions in both Rotate functions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文