namespace BinaryTreeLibrary
{
    // class TreeNode declaration
    class TreeNode
    {
        private TreeNode leftNode; // link to left child
        private int data; // data stored in node
        private TreeNode rightNode; // link to right child
        // initialize data and make this a leaf node
        public TreeNode(int nodeData)
        {
            data = nodeData;
            leftNode = rightNode = null; // node has no children
        } // end constructor
        // LeftNode property
        public TreeNode LeftNode
        {
            get
            {
                return leftNode;
            } // end get
            set
            {
                leftNode = value;
            } // end set
        } // end property LeftNode
        // Data property
        public int Data
        {
            get
            {
                return data;
            } // end get
            set
            {
                data = value;
            } // end set
        } // end property Data
        // RightNode property
        public TreeNode RightNode
        {
            get
            {
                return rightNode;
            } // end get
            set
            {
                rightNode = value;
            } // end set
        } // end property RightNode
        // insert TreeNode into Tree that contains nodes;
        // ignore duplicate values
        public void Insert(int insertValue)
        {
            if (insertValue < data) // insert in left subtree
            {
                // insert new TreeNode
                if (leftNode == null)
                    leftNode = new TreeNode(insertValue);
                else // continue traversing left subtree
                    leftNode.Insert(insertValue);
            } // end if
            else if (insertValue > data) // insert in right subtree
            {
                // insert new TreeNode
                if (rightNode == null)
                    rightNode = new TreeNode(insertValue);
                else // continue traversing right subtree
                    rightNode.Insert(insertValue);
            } // end else if
        } // end method Insert
    } // end class TreeNode
    // class Tree declaration
    public class Tree
    {
        private TreeNode root;
        // construct an empty Tree of integers
        public Tree()
        {
            root = null;
        } // end constructor
        // Insert a new node in the binary search tree.
        // If the root node is null, create the root node here.
        // Otherwise, call the insert method of class TreeNode.
        public void InsertNode(int insertValue)
        {
            if (root == null)
                root = new TreeNode(insertValue);
            else
                root.Insert(insertValue);
        } // end method InsertNode
        // begin preorder traversal
        public void PreorderTraversal()
        {
            PreorderHelper(root);
        } // end method PreorderTraversal
        // recursive method to perform preorder traversal
        private void PreorderHelper(TreeNode node)
        {
            if (node == null)
                return;
            // output node data
            Console.Write(node.Data + " ");
            // traverse left subtree
            PreorderHelper(node.LeftNode);
            // traverse right subtree
            PreorderHelper(node.RightNode);
        } // end method PreorderHelper
        // begin inorder traversal
        public void InorderTraversal()
        {
            InorderHelper(root);
        } // end method InorderTraversal
        // recursive method to perform inorder traversal
        private void InorderHelper(TreeNode node)
        {
            if (node == null)
                return;
            // traverse left subtree
            InorderHelper(node.LeftNode);
            // output node data
            Console.Write(node.Data + " ");
            // traverse right subtree
            InorderHelper(node.RightNode);
        } // end method InorderHelper
        // begin postorder traversal
        public void PostorderTraversal()
        {
            PostorderHelper(root);
        } // end method PostorderTraversal
        // recursive method to perform postorder traversal
        private void PostorderHelper(TreeNode node)
        {
            if (node == null)
                return;
            // traverse left subtree
            PostorderHelper(node.LeftNode);
            // traverse right subtree
            PostorderHelper(node.RightNode);
            // output node data
            Console.Write(node.Data + " ");
        } // end method PostorderHelper
    } // end class Tree
}
