1

Generic implementation in C#. A very quick example, so obviously the code can be improved quite a bit, however at the moment I want to get it to work in its current form.

Adding new nodes, or deleting existing ones, does not work. When the print() method is called in the driver program:

BinarySearchTree<int> testTree = new BinarySearchTree<int>(1);

Console.WriteLine("Binary search tree contains 0: " + testTree.exists(0));
Console.WriteLine("Binary search tree contains 1: " + testTree.exists(1));
Console.WriteLine("Binary search tree contains 2: " + testTree.exists(2));

testTree.add(2);
Console.WriteLine("Binary search tree contains 2: " + testTree.exists(2));
testTree.remove(1);
Console.WriteLine("Binary search tree contains 1: " + testTree.exists(1));
testTree.print();

Console output for the above:

Binary search tree contains 0: False
Binary search tree contains 1: True
Binary search tree contains 2: False
Binary search tree contains 2: False
Binary search tree contains 1: True
1

Checked with setting breakpoints at the appropriate methods, no closer to finding the problem.

Code for this class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace BinaryTree
{
    public class BinarySearchTree<T> where T : IComparable
    {
        #region private members
        private class Node
        {
            public T value;
            public Node left;
            public Node right;
        }

        private Node rootNode;

        private void insert(Node root, Node node)
        {
            if (root==null)
            {
                root = node;
            }
            else if (isLessThan(node.value,root.value))
            {
                insert(node.left, node);
            }
            else if (isGreaterThan(node.value,root.value) || (isEqual(root.value,node.value)))
            {
                insert(node.right, node);
            }
        }

        private void displayInOrder(Node node)
        {
            if (node != null)
            {
                displayInOrder(node.left);
                Console.WriteLine(node.value);
                displayInOrder(node.right);
            }
        }

        #region comparison helper functions
        private bool isGreaterThan(T a, T b)
        {
            return a.CompareTo(b) > 0;
        }

        private bool isLessThan(T a, T b)
        {
            return a.CompareTo(b) < 0;
        }

        private bool isEqual(T a, T b)
        {
            return a.CompareTo(b) == 0;
        }
            #endregion
        #endregion

        // ctor
        public BinarySearchTree(T rootValue)
        {
            rootNode = new Node();
            rootNode.value = rootValue;
            rootNode.left = null;
            rootNode.right = null;
        }

        public void add(T value)
        {
            // first create a new node. Eventually, it will be added to the tree.
            Node newNode = new Node();
            newNode.value = value;
            newNode.left = null;
            newNode.right = null;

            // give this node to the insert method, which will traverse the tree until it finds the correct place to insert it.
            insert(rootNode, newNode);
        }

        public bool exists(T value)
        {
            Node node = rootNode;

            while (node!=null)
            {
                if (isEqual(node.value,value))
                {
                    return true;
                }
                else if (isLessThan(value,node.value))
                {
                    node = node.left;
                }
                else if (isGreaterThan(value,node.value))
                {
                    node = node.right;
                }
            }

            return false;
        }

        public void remove(T value)
        {
            Node node = rootNode;

            while (node!=null)
            {
                if (isEqual(node.value,value))
                {
                    node = null;
                }
                else if (isLessThan(node.value, value))
                {
                    node = node.left;
                }
                else if (isGreaterThan(node.value, value) || (isEqual(value, node.value)))
                {
                    node = node.right;
                }
            }
        }

        public void print()
        {
            displayInOrder(rootNode);
        }   
    }
}

Shahid Manzoor Bhat
  • 1,307
  • 1
  • 13
  • 32
Al2110
  • 566
  • 9
  • 25

1 Answers1

1

Your problem is that you are assigning a value to a null, which is not a reference at all.

The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables. Ordinary value types cannot be null, except for nullable value types.

In this line of code node.right has the value null.

insert(node.right, node);

So you will assign node to a null which is no reference at all.

My suggestion would be to change the insert code like this:

Declare a direction enum

public enum Direction {
    Left,
    Right
}

Use the enum to update the proper reference

private void insert(Node root, Node node)
{
    if (root==null)
    {
        root = node;
    }
    else if (isLessThan(node.value,root.value))
    {
        insert(root, node, Direction.Left);
    }
    else if (isGreaterThan(node.value,root.value) || (isEqual(root.value,node.value)))
    {
        insert(root, node, Direction.Right);
    }
}

private void insert(Node root, Node node, Direction direction)
{
    if (direction == Direction.Left)
    {
        // You are actually updating the reference left of root node
        root.left = node;
    }
    else if (direction == Direction.Right)
    {
        // You are actually updating the reference right of root node
        root.right = node;
    }
}

The remove logic is pretty much the same. Check the comments

// I am declaring a local reference to a Node
Node node = rootNode;

while (node!=null)
{
    if (isEqual(node.value,value))
    {
         // I am updating the local reference to null
         // I am not setting the left or right value reference to null
         // So that I won't be able to find it again
         node = null;
    }

Beware that when you detach one reference, you have to rebuild the whole tree. If you detach a link by setting null on the left, then all the left values will be detached as well.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61