Updated repo to be C# only
This commit is contained in:
		
							
								
								
									
										286
									
								
								Datastructures/BinaryTree/Tree.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								Datastructures/BinaryTree/Tree.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,286 @@
 | 
			
		||||
using C_.Datastructures.LinkedList;
 | 
			
		||||
using C_.Datastructures.Stack;
 | 
			
		||||
using C_.Datastructures.Queue;
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace C_.Datastructures.BinaryTree
 | 
			
		||||
{
 | 
			
		||||
    internal class Tree<T> where T:IComparable
 | 
			
		||||
    {
 | 
			
		||||
        public TreeNode<T>? Root { get; set; }
 | 
			
		||||
        public int Count { get; set; }
 | 
			
		||||
 | 
			
		||||
        public static Tree<T> Create(){
 | 
			
		||||
            //Create a new Tree with no Head
 | 
			
		||||
            return new Tree<T>{
 | 
			
		||||
                Root = null,
 | 
			
		||||
                Count = 0
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Tree<T> Create(T value){
 | 
			
		||||
            //Create a new Tree with Head
 | 
			
		||||
            return new Tree<T>{
 | 
			
		||||
                Root = TreeNode<T>.Create(value)
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Add(T value)
 | 
			
		||||
        {//Add item to the correct position in the tree (Input cannot be null)
 | 
			
		||||
            Count++;
 | 
			
		||||
 | 
			
		||||
            if (Root == default)
 | 
			
		||||
            {//If new node should become the root
 | 
			
		||||
                Root = TreeNode<T>.Create(value);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //Find position to insert
 | 
			
		||||
            TreeNode<T> node = Root;
 | 
			
		||||
            node = Descend(value, node)!;
 | 
			
		||||
 | 
			
		||||
            if (value.CompareTo(node.Value) < 0)
 | 
			
		||||
            {//Insert to left
 | 
			
		||||
                node.Left = TreeNode<T>.Create(value);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            //Insert to right
 | 
			
		||||
            node.Right = TreeNode<T>.Create(value);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Delete(T value)
 | 
			
		||||
        {
 | 
			
		||||
            //Check if root of tree is null
 | 
			
		||||
            if (Count == 0)
 | 
			
		||||
                return false;
 | 
			
		||||
            
 | 
			
		||||
            //Check if the only value is the root
 | 
			
		||||
            if (Count == 1)
 | 
			
		||||
            {
 | 
			
		||||
                if (Root!.Value!.Equals(value))
 | 
			
		||||
                {//If the only item is the one we are trying to delete
 | 
			
		||||
                    Count = 0;
 | 
			
		||||
                    Root = default;
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //Stack to store the items leading up to and including the one we are trying to delete    
 | 
			
		||||
            Stack<TreeNode<T>>? deletionStack;
 | 
			
		||||
 | 
			
		||||
            //Search for item being deleted + Parents
 | 
			
		||||
            deletionStack = Find(value);
 | 
			
		||||
 | 
			
		||||
            if (deletionStack == default)
 | 
			
		||||
                return false; //Item was not found
 | 
			
		||||
 | 
			
		||||
            //Delete Item (replace) and replace pointers to retain integrity of tree
 | 
			
		||||
 | 
			
		||||
            TreeNode<T>? node = deletionStack.Pop();
 | 
			
		||||
 | 
			
		||||
            //stack to store the items leading up to the value that we will use to replace the node
 | 
			
		||||
            Stack<TreeNode<T>>? replacementStack = Min(node!.Right);
 | 
			
		||||
            
 | 
			
		||||
            if (replacementStack == default)
 | 
			
		||||
            {//Nothing to the right of the value we are deleting
 | 
			
		||||
                if (deletionStack.Peek() != default)
 | 
			
		||||
                {//Parent adopts left hand side of node if present
 | 
			
		||||
                    deletionStack.Pop()!.Left = node.Left;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (node.Left != default)
 | 
			
		||||
                {//Node adopts left value if no lower value to the right
 | 
			
		||||
                    node.Value = node.Left!.Value;
 | 
			
		||||
                    node.Left = node.Left.Left;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {//Replace the value + reorder nodes
 | 
			
		||||
                node.Value = replacementStack.Peek()!.Value;
 | 
			
		||||
                TreeNode<T>? replacementNode = replacementStack.Pop();
 | 
			
		||||
 | 
			
		||||
                switch (replacementStack.GetCount())
 | 
			
		||||
                {//Determine what to do based on number of items in replacement stack
 | 
			
		||||
                    case 1:
 | 
			
		||||
                        node.Right = replacementNode!.Right;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case >=2:
 | 
			
		||||
                        replacementStack.Peek()!.Left = replacementNode!.Right;
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Count--;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public LinkedList<T>? Traverse(TraversalType traversalType)
 | 
			
		||||
        {
 | 
			
		||||
            if (Root == default)
 | 
			
		||||
                return default;
 | 
			
		||||
 | 
			
		||||
            LinkedList<T> list = LinkedList<T>.Create();
 | 
			
		||||
 | 
			
		||||
            switch (traversalType)
 | 
			
		||||
            {//Select which type of traversal to do
 | 
			
		||||
                case TraversalType.Inorder:
 | 
			
		||||
                    Inorder(list, Root);
 | 
			
		||||
                    break;
 | 
			
		||||
                case TraversalType.Preorder:
 | 
			
		||||
                    Preorder(list, Root);
 | 
			
		||||
                    break;
 | 
			
		||||
                case TraversalType.Postorder:
 | 
			
		||||
                    Postorder(list, Root);
 | 
			
		||||
                    break;
 | 
			
		||||
                case TraversalType.Breadth:
 | 
			
		||||
                    Queue<TreeNode<T>> queue = Queue<TreeNode<T>>.Create();
 | 
			
		||||
                    BreadthFirst(list, queue, Root);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    return default;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return list;
 | 
			
		||||
        }
 | 
			
		||||
        private void Inorder(LinkedList<T> list, TreeNode<T> node)
 | 
			
		||||
        {//Inorder Traversal
 | 
			
		||||
            if (node.Left != default)
 | 
			
		||||
                Inorder(list, node.Left);
 | 
			
		||||
 | 
			
		||||
            list.Append(node.Value);
 | 
			
		||||
 | 
			
		||||
            if (node.Right != default)
 | 
			
		||||
                Inorder(list, node.Right);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Preorder(LinkedList<T> list, TreeNode<T> node)
 | 
			
		||||
        {//Preorder Traversal
 | 
			
		||||
            list.Append(node.Value);
 | 
			
		||||
            
 | 
			
		||||
            if (node.Left != default)
 | 
			
		||||
                Preorder(list, node.Left);
 | 
			
		||||
 | 
			
		||||
            if (node.Right != default)
 | 
			
		||||
                Preorder(list, node.Right);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Postorder(LinkedList<T> list, TreeNode<T> node)
 | 
			
		||||
        {//Postorder Traversal
 | 
			
		||||
            if (node.Left != default)
 | 
			
		||||
                Postorder(list, node.Left);
 | 
			
		||||
 | 
			
		||||
            if (node.Right != default)
 | 
			
		||||
                Postorder(list, node.Right);
 | 
			
		||||
 | 
			
		||||
            list.Append(node.Value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void BreadthFirst(LinkedList<T> list, Queue<TreeNode<T>> queue, TreeNode<T> node)
 | 
			
		||||
        {//Breadth First Traversal
 | 
			
		||||
            list.Append(node.Value);
 | 
			
		||||
 | 
			
		||||
            if (node.Left != default)
 | 
			
		||||
                queue.Push(node.Left);
 | 
			
		||||
 | 
			
		||||
            if (node.Right != default)
 | 
			
		||||
                queue.Push(node.Right);
 | 
			
		||||
 | 
			
		||||
            //Only continue to traverse if there are no mode nodes to process
 | 
			
		||||
            if (queue.Peek() != default)
 | 
			
		||||
                BreadthFirst(list, queue, queue.Pop()!);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private static TreeNode<T>? GetNext(T value, TreeNode<T>? node)
 | 
			
		||||
        {//T is comparable so use methods to determine which way to traverse
 | 
			
		||||
            if(node == default)
 | 
			
		||||
                return default;
 | 
			
		||||
 | 
			
		||||
            if (value.CompareTo(node.Value) < 0)
 | 
			
		||||
            {//Traverse Left
 | 
			
		||||
                return node.Left;
 | 
			
		||||
            }
 | 
			
		||||
            //Traverse Right
 | 
			
		||||
            return node.Right;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Stack<TreeNode<T>>? Find(T value)
 | 
			
		||||
        {//Return true if the item can be found within the tree
 | 
			
		||||
            if (Root == default || Root.Value!.Equals(default))
 | 
			
		||||
                return default;
 | 
			
		||||
 | 
			
		||||
            Stack<TreeNode<T>>? stack = Stack<TreeNode<T>>.Create(Root);
 | 
			
		||||
 | 
			
		||||
            while (stack.Peek() != default)
 | 
			
		||||
            {
 | 
			
		||||
                //Compare value at node to see if we are looking for the root item
 | 
			
		||||
                if (stack.Peek()!.Value!.Equals(value))
 | 
			
		||||
                    return stack;
 | 
			
		||||
 | 
			
		||||
                stack.Push(GetNext(value, stack.Peek()));
 | 
			
		||||
            }
 | 
			
		||||
            return default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Stack<TreeNode<T>>? Min(TreeNode<T>? node)
 | 
			
		||||
        {//Returns a Stack with the value on top being the minimum of the subtree
 | 
			
		||||
            
 | 
			
		||||
            if(node == default)
 | 
			
		||||
                return default;
 | 
			
		||||
 | 
			
		||||
            //Stack to store and be able to get the parent values
 | 
			
		||||
            Stack<TreeNode<T>> stack = Stack<TreeNode<T>>.Create(node);
 | 
			
		||||
 | 
			
		||||
            while(true){
 | 
			
		||||
                if (stack.Peek()!.Left == default)
 | 
			
		||||
                    return stack;
 | 
			
		||||
 | 
			
		||||
                stack.Push(stack.Peek()!.Left);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Stack<TreeNode<T>>? Max(TreeNode<T>? node)
 | 
			
		||||
        {///Returns a Stack with the value on top being the maximum of the subtree
 | 
			
		||||
            if(node == default)
 | 
			
		||||
                return default;
 | 
			
		||||
 | 
			
		||||
            //Stack to store and be able to get the parent values
 | 
			
		||||
            Stack<TreeNode<T>> stack = Stack<TreeNode<T>>.Create(node);
 | 
			
		||||
 | 
			
		||||
            while(true){
 | 
			
		||||
                if (stack.Peek()!.Right == default)
 | 
			
		||||
                    return stack;
 | 
			
		||||
 | 
			
		||||
                stack.Push(stack.Peek()!.Right);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private TreeNode<T>? Descend(T value, TreeNode<T>? current)
 | 
			
		||||
        {//Keep trying to determine whether to go left or right until null node is found that can be appended to
 | 
			
		||||
            if (current == default)
 | 
			
		||||
                return default;
 | 
			
		||||
 | 
			
		||||
            TreeNode<T>? node;
 | 
			
		||||
 | 
			
		||||
            node = Descend(value, GetNext(value, current));
 | 
			
		||||
            if (node == null)
 | 
			
		||||
            {
 | 
			
		||||
                return current;
 | 
			
		||||
            }
 | 
			
		||||
            return node;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public enum TraversalType
 | 
			
		||||
    {//Enum to allow for Traversal selection
 | 
			
		||||
        Inorder,
 | 
			
		||||
        Preorder,
 | 
			
		||||
        Postorder,
 | 
			
		||||
        Breadth
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								Datastructures/BinaryTree/TreeNode.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Datastructures/BinaryTree/TreeNode.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using C_.Datastructures.Generic;
 | 
			
		||||
 | 
			
		||||
namespace C_.Datastructures.BinaryTree
 | 
			
		||||
{
 | 
			
		||||
    internal class TreeNode<T> : DirectedNode<T, TreeNode<T>>
 | 
			
		||||
    {
 | 
			
		||||
        //All properties inherited from base class
 | 
			
		||||
        public static TreeNode<T> Create(T value){
 | 
			
		||||
            //Create a new node without any children
 | 
			
		||||
            return new TreeNode<T>{
 | 
			
		||||
                Value = value
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static TreeNode<T> Create(T value, TreeNode<T>? left, TreeNode<T>? right){
 | 
			
		||||
            //Create a new node with the option of having children
 | 
			
		||||
            return new TreeNode<T>{
 | 
			
		||||
                Value = value,
 | 
			
		||||
                Left = left,
 | 
			
		||||
                Right = right
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user