//Methods
 public void insert(int value, BSTNode location)
 {
     //if less than go left
     if(value < location.Value)
     {
         if(location.leftChildPointer != null)
         {
             insert(value, location.leftChildPointer);
         }
         else
         {
             location.leftChildPointer = new BSTNode(value, location);
         }
     }
     //otherwise go right
     else
     {
         if (location.rightChildPointer != null)
         {
             insert(value, location.rightChildPointer);
         }
         else
         {
             location.rightChildPointer = new BSTNode(value, location);
         }
     }
 }
 public BSTNode(int value, BSTNode parent)
 {
     this.value = value;
     lcp = null;
     rcp = null;
     par = parent;
 }
 public BSTNode(int value)
 {
     this.value = value;
     lcp = null;
     rcp = null;
     par = null;
 }
        public void delete(int value, BSTNode start)
        {
            if(isFound(value))
            {
                BSTNode toDelete = search(value, start);

                //our node we want to delete has no children we can just remove him
                if(toDelete.rightChildPointer == null && toDelete.leftChildPointer == null)
                {
                    //we need to discover what side of the parent we are on
                    if(toDelete.Parent.leftChildPointer != null && toDelete.Parent.leftChildPointer.Value == toDelete.Value)
                    {
                        toDelete.Parent.leftChildPointer = null;
                    }
                    if(toDelete.Parent.rightChildPointer != null && toDelete.Parent.rightChildPointer.Value == toDelete.Value)
                    {
                        toDelete.Parent.rightChildPointer = null;
                    }
                }
                else
                {
                    //our node we want to delete has two children 
                    if(toDelete.rightChildPointer != null && toDelete.leftChildPointer != null)
                    {
                        BSTNode lowest = findMin(toDelete.rightChildPointer);
                        toDelete.Value = lowest.Value;
                        delete(toDelete.Value, toDelete.rightChildPointer);
                    }
                    else
                    {
                        //the node we want to delete has only a left child
                        if(toDelete.leftChildPointer != null && toDelete.rightChildPointer == null)
                        {
                            if (toDelete.Parent.leftChildPointer != null && toDelete.Parent.leftChildPointer.Value == toDelete.Value)
                            {
                                toDelete.Parent.leftChildPointer = toDelete.leftChildPointer;
                                toDelete.Parent.leftChildPointer.Parent = toDelete.Parent;
                            }
                            if (toDelete.Parent.rightChildPointer != null && toDelete.Parent.rightChildPointer.Value == toDelete.Value)
                            {
                                toDelete.Parent.rightChildPointer = toDelete.leftChildPointer;
                                toDelete.Parent.rightChildPointer.Parent = toDelete.Parent;
                            }
                        }
                        //the node that we want to delete only has a right child
                        else
                        {

                            if (toDelete.Parent.leftChildPointer != null && toDelete.Parent.leftChildPointer.Value == toDelete.Value)
                            {
                                toDelete.Parent.leftChildPointer = toDelete.rightChildPointer;
                                toDelete.Parent.leftChildPointer.Parent = toDelete.Parent;
                            }
                            if (toDelete.Parent.rightChildPointer != null && toDelete.Parent.rightChildPointer.Value == toDelete.Value)
                            {
                                toDelete.Parent.rightChildPointer = toDelete.rightChildPointer;
                                toDelete.Parent.rightChildPointer.Parent = toDelete.Parent;
                            }
                        }
                    }
                }

            }
        }
        public void PrintTreeDFSPostOrder(BSTNode location)
        {
            if (location.leftChildPointer != null)
            {
                PrintTreeDFSPostOrder(location.leftChildPointer);
            }

            if (location.rightChildPointer != null)
            {
                PrintTreeDFSPostOrder(location.rightChildPointer);
            }

            Console.Write(location.Value + ", ");
        }
 //Constructors
 public BinarySearchTree(int root)
 {
     this.root = new BSTNode(root);
 }
        public BSTNode search(int value, BSTNode location)
        {
            BSTNode ReturnNode = null;

            if(location.Value == value)
            {
                return location;
            }
            if (location.Value > value && location.leftChildPointer != null)
            {
                ReturnNode = search(value, location.leftChildPointer);
            }
            if (location.Value < value && location.rightChildPointer != null)
            {
                ReturnNode = search(value, location.rightChildPointer);
            }

            return ReturnNode;
        }
        public BSTNode findMin(BSTNode location)
        {
            BSTNode returned;

            if(location.leftChildPointer != null)
            {
                returned = findMin(location.leftChildPointer);
            }
            else
            {
                returned = location;
            }
            return returned;
        }
 public static int secondLargest(BSTNode location, int leftCount = 0)
 {
     if (location.rightChildPointer != null)
     {
         return secondLargest(location.rightChildPointer, leftCount);
     }
     else
     {
         if (leftCount == 0 && location.leftChildPointer != null)
         {
             leftCount = 1;
             return secondLargest(location.leftChildPointer, leftCount);
         }
         else
         {
             if (leftCount == 1)
             {
                 return location.Value;
             }
             else
             {
                 return location.Parent.Value;
             }
         }
     }
 }
        public static bool isTree(BSTNode location)
        {
            bool returnValue = true;

            if (location.leftChildPointer != null && location.Value > location.leftChildPointer.Value)
            {
                returnValue = returnValue & isTree(location.leftChildPointer);
            }
            else
            {
                if(location.leftChildPointer != null)
                {
                    returnValue = false;
                }
            }
            if (location.rightChildPointer != null && location.Value < location.rightChildPointer.Value)
            {
                returnValue = true;
                returnValue = returnValue & isTree(location.leftChildPointer);
            }
            else
            {
                if (location.rightChildPointer != null)
                {
                    returnValue = false;
                }
            }

            return returnValue;
        }
 public static bool isSumTree(BSTNode location)
 {
     bool returnValue = true;
     //we have two children
     if (location.rightChildPointer != null && location.leftChildPointer != null)
     {
         if ((location.leftChildPointer.Value + location.rightChildPointer.Value) == location.Value)
         {
             returnValue = returnValue & isSumTree(location.leftChildPointer);
             returnValue = returnValue & isSumTree(location.rightChildPointer);
         }
         else
         {
             returnValue = false;
         }
     }
     else
     {
         //only have one child to the left
         if (location.rightChildPointer != null && location.leftChildPointer == null)
         {
             if (location.rightChildPointer.Value == location.Value)
             {
                 returnValue = returnValue & isSumTree(location.rightChildPointer);
             }
             else
             {
                 returnValue = false;
             }
         }
         else
         {
             //only have one child to the left
             if (location.rightChildPointer == null && location.leftChildPointer != null)
             {
                 if (location.leftChildPointer.Value == location.Value)
                 {
                     returnValue = returnValue & isSumTree(location.leftChildPointer);
                 }
                 else
                 {
                     returnValue = false;
                 }
             }
         }
         //no children so lets return true
         if (location.rightChildPointer == null && location.leftChildPointer == null)
         {
             returnValue = true;
         }
     }
     return returnValue;
 }