【问题标题】:Recursive binary tree递归二叉树
【发布时间】:2014-03-29 12:17:18
【问题描述】:

基本上我的问题是我需要一个 addNode 方法,它的签名是这样的:

addNode(Node thisNode, Node toAdd)

我当前的方法签名是:

AddRecursively(null, usersInput);

null (node) 因为它是一种递归方法,我需要将值传递回该方法。 usersInput 是一个整数。

我不知道如何在仍然使用递归的同时做我被告知要做的事情。

请注意: 如果可能,请尝试以简单的方式解释您的代码,我不太擅长编程。

我的代码应该可以工作,因为它基于我的旧代码,它确实可以工作,但我尚未对其进行测试,并且 Node findNode 已被保留,因为我应该使用两个节点,但我不知道如何做到这一点老实说。

public void AddRecursively(Node findNode, Node findNextNode, int usersInput)//don't need findNode i think
{
    if (root.value == null)
    {
        root.value = usersInput; //if no root, make it (everytime it is run it will have no root)
    }
    else if (usersInput > root.value && root.right == null)
    {
        root.right.value = usersInput; //first right of node
    }
    else if (usersInput < root.value && root.left == null)
    {
        root.left.value = usersInput; //first left of node 
    }
    //recursive
    else if (usersInput > root.right.value && root.right != null && findNextNode == null)
    {
        findNextNode = root.right; //setting up recursive right
    }
    else if (usersInput < root.left.value && root.left != null && findNextNode == null)
    {
        findNextNode = root.left; //setting up recursive left
    }
    //adding values before doing recursive
    else if (usersInput > findNextNode.right.value && findNextNode.right == null)
    {
        findNextNode.right.value = usersInput; //if the next right is empty add
    }
    else if (usersInput < findNextNode.left.value && findNextNode.left == null)
    {
        findNextNode.left.value = usersInput; //if next left is empty add
    }
    //recursive, should be able to handle left.left.right for example as findNextNode could be right.right then it could = right.right.left
    else if (usersInput > findNextNode.right.value && findNextNode.right != null)
    {
        findNextNode = findNextNode.right;
        AddRecursively(null, findNextNode, usersInput);
    }
    else if (usersInput < findNextNode.left.value && findNextNode.left != null)
    {
        findNextNode = findNextNode.left;
        AddRecursively(null, findNextNode, usersInput);
    }
}

【问题讨论】:

  • 我不太明白这个问题,你的代码不起作用?
  • @AlejandroPiad 我的代码确实可以工作,但它没有接受两个输入节点,即 add 方法所在的节点和要访问的下一个节点。目前它只接受它想去的节点。对不起,这是一个措辞糟糕的帖子!我只是不太确定自己该说什么。我的代码唯一的问题是它没有按照首席开发人员想要的方式完成。(我正在学习 c#)
  • 递归是一种以简洁的方式编写困难代码的方法。这件艺术品看起来像一个简洁的东西写在一个困难的是:-)
  • @user3245390 我认为问题可能是您的方法是实例方法,因此您当前所在的节点是this,因此无需将其指定为参数。从“首席开发人员”想要的签名来看,我猜他希望这是一个静态方法,而不是实例方法,因此您需要传递当前节点以及要添加的节点。它与递归无关,两种方式都是递归完成的(实例或静态)。只是 this 是隐含的还是显式声明的。也许您需要考虑是否需要实例或静态方法...
  • @lbohuizen 谢谢你的夸奖:)!关于我与首席开发人员进行的讨论的一些更新。他没有时间去复习“不正确”的地方,但他说了这句话。也许它有助于澄清我所追求的(引用他所说的话):“我怀疑我今天是否有时间来做那件事,我害怕。你需要两个节点,因为你需要一个您正在添加并且您需要当前正在查看的那个。除非您的代码不正确,否则它们不应该以任何其他方式提供给您”

标签: c# recursion data-structures binary-tree


【解决方案1】:

这不一定是我喜欢的方式,但为了回答你的具体问题,我会坚持你提出的签名。

首先我假设你有以下类结构:

class BinaryTree<T> where T: IComparable<T> {
    private Node root;

    // ....

    // The public Add interface (might be different for you)
    public void Add(T value) {
        if (this.root == null) {
            // Handle the special empty case
            this.root = new Node() { Value = value };
        } 
        else {
            // Just call the private one with the right values
            this.Add(this.root, new Node() { Value = value });
        }
    }

    // This is where the recursive magic happens
    private void Add(Node current, Node toAdd) {
        // This one comes next...
    }

    class Node {
        public T Value;
        public Node Left;
        public Node Right;
    }
}

我为树本身使用了与Node 不同的类,因为它可以更轻松地处理null 节点,并且如果稍后您决定制作平衡树(AVL、红黑等)。 ) 从外部操作Node 实例会容易得多。

此外,泛型类型T 可能不能为空,但Node 可以。请注意,T 必须是 IComparable&lt;T&gt;。在您的情况下,int 就足够了。

现在,让我们进入递归方法。

// ....

private void Add(Node current, Node toAdd) {
    // From here on neither `current.Value` nor `toAdd.Value` are ever null
    if (toAdd.Value.CompareTo(current.Value) <= 0) {
         // We go left
         if (current.Left == null) {
             current.Left = toAdd;
         }
         else {
             Add(node.Left, toAdd);
         }
    }
    else {
         // We go right
         if (current.Right == null) {
             current.Right = toAdd;
         }
         else {
             Add(node.Right, toAdd);
         }          
    }
}

我想就是这样。

现在,如果您问我,如果我们允许私有 Add 实现返回添加的节点,则该方法可以缩短一点。

// ....

private Node Add(Node current, Node toAdd) {
    if (current == null) {
         return toAdd;
    }

    if (toAdd.Value.CompareTo(current.Value) <= 0) {
         current.Left = Add(current.Left, toAdd);
    }
    else {
         current.Right = Add(current.Right, toAdd);
    }

    return current;
}

然后公众号Add也比较简单

public void Add(T value) {
    this.root = Add(this.root, new Node() { Value = value });
}

正如@Iboshuizen 所说,递归允许您用简单的语句说出复杂的事情。

希望它能让你的老板开心;)。

【讨论】:

  • 在二叉搜索树的完整实现中,您将有一个 Find 递归方法,它返回找到的节点或树中最近的节点。那么AddRemove都可以通过调用Find轻松实现。
猜你喜欢
  • 2016-04-19
  • 2010-12-07
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 2016-07-20
  • 2014-01-02
  • 2012-10-29
相关资源
最近更新 更多