【问题标题】:Remove a node from binary search tree iteratively迭代地从二叉搜索树中删除一个节点
【发布时间】:2018-10-22 21:28:30
【问题描述】:

我有三种方法用于删除 BST 中的节点。 RemoveRecRemoveNonRec 方法递归迭代搜索节点,Remove 删除找到的节点。

private void RemoveRec(int value, ref TreeNode node)
{
    if (node != null)
    {
        if (value < node.Value)
        {
            RemoveRec(value, ref node.Left);
        }
        else if (value > node.Value)
        {
            RemoveRec(value, ref node.Right);
        }
        else
        {
            Remove(value, ref node);
        } 
    } 
}

public void RemoveNonRec(int value)
{
    ref TreeNode node = ref this.Root;
    while (node != null)
    {
        if (value < node.Value)
        {
            node = node.Left;
        }
        else if (value > node.Value)
        {
            node = node.Right;
        }
        else
        {
            Remove(value, ref node);
            break;
        }
    }
}

private void Remove(int value, ref TreeNode node)
{
    if (node != null)
    {
        if (node.Counter > 1)
        {
            --node.Counter;
            Console.WriteLine("Deleted element: {0}, elements in the node: {1}", node.Value, node.Counter);
        }
        else
        {
            int vMes = node.Value;

            if (node.Left == null && node.Right == null)
            {
                node = null;
            }
            else if (node.Left != null && node.Right == null)
            {
                node = node.Left;
            }
            else if (node.Left == null && node.Right != null)
            {
                node = node.Right;
            }
            else
            {
                if (node.Right.Left == null)
                {
                    node.Right.Left = node.Left;
                    node = node.Right;
                }
                else
                {
                    TreeNode p = node.Right;
                    while (p.Left.Left != null)
                       p = p.Left;
                    TreeNode q = p.Left;
                    p.Left = q.Right;
                    q.Left = node.Left;
                    q.Right = node.Right;
                    node = q;
                }
            }

            Console.WriteLine("Deleted node: {0}", vMes);
        }
    }
}

问题是RemoveNonRec 不能正常工作,我知道为什么。但是我不知道如何使它工作。

【问题讨论】:

    标签: c# recursion iteration binary-search-tree


    【解决方案1】:

    作为一种解决方案,您可以在返回引用的 TreeNode 类中添加这两个方法。

    private TreeNode left;
    private TreeNode right;
    
    public ref TreeNode GetLeft()
    {
        return ref left;
    }
    
    public ref TreeNode GetRight()
    {
        return ref right;
    }
    

    因此您不再访问这些属性。相反,您调用这两个方法:

    private void RemoveRec(int value, ref TreeNode node)
    {
        if (node != null)
        {
            if (value < node.Value)
            {
                RemoveRec(value, ref node.GetLeft());
            }
            else if (value > node.Value)
            {
                RemoveRec(value, ref node.GetRight());
            }
            else
            {
                Remove(value, ref node);
            }
        }
    }
    
    public void RemoveNonRec(int value)
    {
        if(value == Root.Value)
        {
            Remove(value, ref Root);
        }
        else
        {
            TreeNode node = Root;
    
            while (node != null)
            {
                if (value < node.Value)
                {
                    node = node.GetLeft();
                }
                else if (value > node.Value)
                {
                    node = node.GetRight();
                }
                else
                {
                    Remove(value, ref node);
                    break;
                }
            }
        }
    }
    
    private void Remove(int value, ref TreeNode node)
    {
        if (node != null)
        {
            if (node.Counter > 1)
            {
                --node.Counter;
                Console.WriteLine("Deleted element: {0}, elements in the node: {1}", node.Value, node.Counter);
            }
            else
            {
                int vMes = node.Value;
                ref TreeNode left = ref node.GetLeft();
                ref TreeNode right = ref node.GetRight();
    
                if (left == null && right == null)
                {
                    node = null;
                }
                else if (left != null && right == null)
                {
                    node = left;
                }
                else if (left == null && right != null)
                {
                    node = right;
                }
                else
                {
                    if (node.GetRight().GetLeft() == null)
                    {
                        node.GetRight().GetLeft() = left;
                        node = right;
                    }
                    else
                    {
                        TreeNode p = right;
                        ref TreeNode leftLeft = ref p.GetLeft().GetLeft();
                        while (leftLeft != null)
                            p = p.GetLeft();
                        ref TreeNode q = ref p.GetLeft();
                        p.GetLeft() = q.GetRight();
                        q.GetLeft() = node.GetLeft();
                        q.GetRight() = node.GetRight();
                        node = q;
                    }
                }
    
                Console.WriteLine("Deleted node: {0}", vMes);
            }
        }
    }
    

    【讨论】:

    • 不,它在ref 下划线并告诉它是意外令牌。
    • 你使用的是哪个c#版本?
    • 我使用的是 c# 7.0
    • 您的代码仍然无法正常工作。问题是,当我在声明ref TreeNode node = ref this.Root; 时使用ref 时,当我将node.Leftnode.Right 分配给node 时,根节点总是被已删除元素的某些子节点覆盖。这就是问题所在。但我找到了解决办法。
    • 哦抱歉,我没有看你的Remove方法
    【解决方案2】:

    我已经设法解决了这个问题。现在可以正常使用了

    public void RemoveNonRec(int value)
    {
        TreeNode node = Root;
        while (node != null)
        {
            if (value < node.Value)
            {
                if (node.Left != null && node.Left.Value == value)
                {
                    Remove(value, ref node.Left);
                    break;
                }
                node = node.Left;
            }
            else if (value > node.Value)
            {
                if (node.Right != null && node.Right.Value == value)
                {
                    Remove(value, ref node.Right);
                    break;
                }
                node = node.Right;
            }
            else
            {
                Remove(value, ref Root);
                break;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多