0

I'm trying to learn about the difference between red-black-trees, list and hashmaps and I havn't been able to get the red-black-tree that I found online to work. It keeps throwing a 'Object reference not set to an instance of an object error' and I can't find the reason why. This is my code.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace CSC510___HashMaps
{
    struct  UserInfo
    {
        public int userId;
        public string userName;
        public UserInfo(int id, string name)
        {
            userId = id;
            userName = name;
        }
    }

    class Program
    {
        static Hashtable userInfoHash;
        static List<UserInfo> userInfoList;
        
        static Stopwatch sw;

        static void Main(string[] args)
        {
            userInfoHash = new Hashtable();
            userInfoList = new List<UserInfo>();
            RedBlackTree userInfoTree = new RedBlackTree();
            
            sw = new Stopwatch();

            //Adding
            for (int i = 0; i < 4000000; i++)
            {
                userInfoHash.Add(i, "user" + i);
                userInfoList.Add(new UserInfo(i, "user" + i));
                userInfoTree.TreeInsert("user" + i);
            }

            //Removing
            if (userInfoHash.ContainsKey(0))
            {
                userInfoHash.Remove(0);
            }

            //Setting
            if (userInfoHash.ContainsKey(1))
            {
                userInfoHash[1] = "replacementName";
            }

            //Looping 
            /*foreach (DictionaryEntry entry in userInfoHash)
            {
                Console.WriteLine("Key: " + entry.Key + " / Value: " + entry.Value);
            }*/

            //Access
            //Near Constant O(1) lookup times on massively scaled collections
            //Using a stopwatch to show difference between list and hashmap
            Random randomUserGen = new Random();
            int randomUser = -1;
            IComparable irandomUser = randomUser;

            sw.Start();
            float startTime = 0;
            float endTime = 0;
            float deltaTime = 0;

            int cycles = 5;
            int cycle = 0;
            string userName = string.Empty;

            while (cycle < cycles)
            {
                randomUser = randomUserGen.Next(3000000, 4000000);

                
                startTime = sw.ElapsedMilliseconds;
                //access from list
                userName = GetUserFromList(randomUser);
                endTime = sw.ElapsedMilliseconds;
                deltaTime = endTime - startTime;
                Console.WriteLine("Time taken to retrieve " + userName + "from list took " + string.Format("{0:0.##}", deltaTime) + "ms");

                startTime = sw.ElapsedMilliseconds;
                userName = (string)userInfoTree.Search(randomUser);
                endTime = sw.ElapsedMilliseconds;
                deltaTime = endTime - startTime;
                Console.WriteLine("Time taken to retrieve " + userName + "from tree took " + string.Format("{0:0.##}", deltaTime) + "ms");

                
                startTime = sw.ElapsedMilliseconds;
                //access from hash
                userName = (string)userInfoHash[randomUser];
                endTime = sw.ElapsedMilliseconds;
                deltaTime = endTime - startTime;
                Console.WriteLine("Time taken to retrieve " + userName + "from hash took " + string.Format("{0:0.##}", deltaTime) + "ms");

                Console.WriteLine();

                cycle++;
            }

        }

        static string GetUserFromList(int userId)
        {
            for (int i = 0; i < userInfoList.Count; i++)
            {
                if (userInfoList[i].userId == userId)
                {
                    return userInfoList[i].userName;
                }
            }

            return string.Empty;
        }

        //Tree stuff (Red-Black)
        public enum Color
        {
            Red = 0, Black = 1
        }

        public enum Direction
        {
            Left,
            Right
        }

        public class Node
        {
            public IComparable data;
            public Node left;
            public Node right;
            public Color color = Color.Black;
            public Node(IComparable data) : this(data, null, null) { }
            public Node(IComparable data, Node left, Node right)
            {
                this.data = data;
                this.left = left;
                this.right = right;
            }
        }

        public class Tree
        {
            protected Node root;
            protected Node freshNode;
            protected Node currentNode;
            protected Tree()
            {
                freshNode = new Node(null);
                freshNode.left = freshNode.right = freshNode;
                root = new Node(null);
            }

            protected int Compare(IComparable item, Node node)
            {
                if (item != root) return item.CompareTo(node.data);
                else return 1;
            }

            public IComparable Search(IComparable data)
            {
                
                freshNode.data = data;
                currentNode = root.right;

                while (true)
                {
                    if (Compare(data, currentNode) < 0) currentNode = currentNode.left;
                    else if (Compare(data, currentNode) > 0) currentNode = currentNode.right;
                    else if (currentNode != freshNode) return currentNode.data;
                    else return null;
                }
            }

            protected void Display()
            {
                this.Display(root.right);
            }

            protected void Display(Node temp)
            {
                if (temp != freshNode)
                {
                    Display(temp.left);
                    Console.WriteLine(temp.data);
                    Display(temp.right);
                }
            }
        }

        public sealed class RedBlackTree: Tree
        {
            private Color Black = Color.Black;
            private Color Red = Color.Red;
            private Node parentNode;
            private Node grandParentNode;
            private Node tempNode;

            public void TreeInsert(IComparable item)
            {
                currentNode = parentNode = grandParentNode = root;
                freshNode.data = item;
                int returnedValue = 0;

                while(Compare(item, currentNode) != 0)
                {
                    tempNode = grandParentNode;
                    grandParentNode = parentNode;
                    parentNode = currentNode;
                    returnedValue = Compare(item, currentNode);

                    if (returnedValue < 0) currentNode = currentNode.left;
                    else currentNode = currentNode.right;
                    if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red) ReArrange(item);
                }

                if(currentNode == freshNode)
                {
                    currentNode = new Node(item, freshNode, freshNode);

                    if (Compare(item, parentNode) < 0) parentNode.left = currentNode;
                    else parentNode.right = currentNode;
                    ReArrange(item);
                }
            }

            private void ReArrange(IComparable item)
            {
                currentNode.color = Red;
                currentNode.left.color = Color.Black;
                currentNode.right.color = Color.Black;

                if (parentNode.color == Color.Red)
                {
                    grandParentNode.color = Color.Red;
                    bool compareWithGrandParentNode = (Compare(item, parentNode) < 0);
                    bool compareWithParentNode = (Compare(item, parentNode) < 0);

                    if (compareWithGrandParentNode != compareWithParentNode) parentNode = Rotate(item, grandParentNode);

                    currentNode = Rotate(item, tempNode);
                    currentNode.color = Black;
                }
                root.right.color = Color.Black;
            }

            private Node Rotate(IComparable item,  Node parentNode)
            {
                int value;

                if (Compare(item, parentNode) < 0)
                {
                    value = Compare(item, parentNode.left);

                    if (value < 0) parentNode.left = this.Rotate(parentNode.left, Direction.Left);
                    else parentNode.left = this.Rotate(parentNode.left, Direction.Right);

                    return parentNode.left;
                }
                else
                {
                    value = Compare(item, parentNode.right);

                    if (value < 0) parentNode.right = this.Rotate(parentNode.right, Direction.Left);
                    else parentNode.right = this.Rotate(parentNode.right, Direction.Right);

                    return parentNode.right; 
                }
            }

            private Node Rotate(Node node, Direction direction)
            {
                Node tempNode;

                if (direction == Direction.Left)
                {
                    tempNode = node.left;
                    node.left = tempNode.right;
                    tempNode.right = node;

                    return tempNode;
                }
                else
                {
                    tempNode = node.right;
                    node.right = tempNode.left;
                    tempNode.right = node;

                    return tempNode;
                }
            }
        }
    }
}

The problem is in this block of code:

public void TreeInsert(IComparable item)
            {
                currentNode = parentNode = grandParentNode = root;
                freshNode.data = item;
                int returnedValue = 0;

                while(Compare(item, currentNode) != 0)
                {
                    tempNode = grandParentNode;
                    grandParentNode = parentNode;
                    parentNode = currentNode;
                    returnedValue = Compare(item, currentNode);

                    if (returnedValue < 0) currentNode = currentNode.left;
                    else currentNode = currentNode.right;
                    if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red) ReArrange(item);
                }

                if(currentNode == freshNode)
                {
                    currentNode = new Node(item, freshNode, freshNode);

                    if (Compare(item, parentNode) < 0) parentNode.left = currentNode;
                    else parentNode.right = currentNode;
                    ReArrange(item);
                }
            }

This line specifically:

   if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red) ReArrange(item);

It keeps saying currentNode is null.

Thank you for your help!

0 Answers0