Question How change root of Tree custom when pass to Recursive function?

Elad770

Member
Joined
Oct 4, 2021
Messages
20
Programming Experience
1-3
Hello I have a problem with tree,
I want to change the root of the tree that has two nodes left and right. To solve this there is the classic solution that c# proposes to move the object to the function as a ref, but the problem is that because the function is recursive and I always call the function with the left hand and once with the right hand,
I can not pass the node to a function in this way
C#:
private void AnalyzeTree(ref Node tree)
{
    if (tree == null || tree.OpratorOrOprend==")")
    {
        return;
    }
    if (tree.OpratorOrOprend == "(")
    {
        tree = tree.Left;
    }
    /*Here i get a complication error
    A property or indexer may not be passed as an out or ref */
    AnalyzeTree(ref tree.Left);
    
    AnalyzeTree(ref tree.Right);
    //next code ....
}
It also has a solution define variable that will save the left node and send it via ref and the same with the right node. The point in the logic of my code is it conflicts with all sorts of little things. Is there a simple way without defining a variable and assigning it?
 
Use a temporary variable.

Instead of
C#:
AnalyzeTree(ref tree.Left);

Do:
C#:
var left = tree.Left
AnalyzeTree(ref left);
tree.Left = left;
 
I'm guessing that you (or someone else transliterated) some C code into C#. It you step back and look at other implementations of the same thing, you can likely find the Pascal and Java versions which take a slightly different tack. They would do the same thing like this:
C#:
private Node AnalyzeTree(Node tree)
{
    if (tree == null || tree.OpratorOrOprend==")")
    {
        return tree;
    }
    if (tree.OpratorOrOprend == "(")
    {
        tree = tree.Left;
    }
    tree.Left = AnalyzeTree(tree.Left);
    
    tree.Right = AnalyzeTree(tree.Right);
    //next code ....
}

Since C# is very Java like, I recommend following suit.
 
You guessed it, yes I took a code I implemented in C and converted it to C#, which is annoying that at some point C is more flexible in recursion with pointers and very easy to change the root of the node with double pointer, than C# in data structure like Tree and need to change The root itself while worthwhile recursion it is not possible to move the right / left son to further reading of the same recursive function. Still, the emphasis is not on the boys themselves (which can be changed exactly in C without the need for a double pointer) but on the very actual change of the root here:
C#:
  if (tree.OpratorOrOprend == "(")
  {
      //here after i return from the readings of the
      //function at this point in time the tree has not changed.
      tree = tree.Left;
  }
Thank you.
I tried by the way the solution is similar to yours it did not exactly do the desired result according to the logic of the code.
I found another way to get around my problem.
 
What is the type of your Node? Is it a class or a struct? I can see things not working quite right if it was a struct?
 
class very simple and right that a structure, as opposed to a class, is defined as by value
C#:
    internal class Node
    {
        public string OpratorOrOprend { set; get; }
        public Node Left { set; get; }
        public Node Right { set; get; }
    }
 
You must have some other bit of logic that needs the updates to happen instantly as side effects because for my usage, the approach of returning the intended change works just fine.

C#:
#nullable enable

using System;

var values = new[] { 50, 25, 75, 10, 30, 5, 7, 3, 70, 80 };

Node<int>? returnTree = null;
foreach(var value in values)
    returnTree = TreeInsert(returnTree, value);

Console.WriteLine("Tree built using return values");
DumpTree(returnTree);

Node<int>? refTree = null;
foreach (var value in values)
    TreeInsertRef(ref refTree, value);

Console.WriteLine("Tree built using ref parameters");
DumpTree(refTree);


Node<T> TreeInsert<T>(Node<T>? node, T value) where T : IComparable<T>
{
    if (node == null)
        return new Node<T>(value);

    var compare = value.CompareTo(node.Value);
    if (compare < 0)
        node.Left = TreeInsert<T>(node.Left, value);
    else if (compare > 0)
        node.Right = TreeInsert<T>(node.Right, value);
    else
        throw new InvalidOperationException();
    return node;
}

void TreeInsertRef<T>(ref Node<T>? node, T value) where T : IComparable<T>
{
    if (node == null)
    {
        node = new Node<T>(value);
        return;
    }

    var compare = value.CompareTo(node.Value);
    if (compare < 0)
    {
        var temp = node.Left;
        TreeInsertRef<T>(ref temp, value);
        node.Left = temp;
    }
    else if (compare > 0)
    {
        var temp = node.Right;
        TreeInsertRef<T>(ref temp, value);
        node.Right = temp;
    }
    else
    {
        throw new InvalidOperationException();
    }
}

void DumpTree<T>(Node<T>? root)
{
    if (root == null)
        return;

    Console.WriteLine(root.Value);
    DumpChild("", root.Left, root.Right != null);
    DumpChild("", root.Right, false);

    void DumpChild(string pad, Node<T>? node, bool hasSibling)
    {
        if (node == null)
            return;

        Console.Write(pad);
        Console.Write(hasSibling ? "+-" : "--");
        Console.WriteLine(node.Value);

        pad += hasSibling ? "| " : "  ";
        DumpChild(pad, node.Left, node.Right != null);
        DumpChild(pad, node.Right, false);
    }
}

class Node<T>
{
    public T Value { get; set; }
    public Node<T>? Left { get; set; }
    public Node<T>? Right { get; set; }

    public Node(T value) => Value = value;
}

NetFiddle: C# Online Compiler | .NET Fiddle
 
Back
Top Bottom