using C_.Datastructures.LinkedList; using C_.Datastructures.Stack; using C_.Datastructures.Queue; using System; namespace C_.Datastructures.BinaryTree { internal class Tree where T:IComparable { public TreeNode? Root { get; set; } public int Count { get; set; } public static Tree Create(){ //Create a new Tree with no Head return new Tree{ Root = null, Count = 0 }; } public static Tree Create(T value){ //Create a new Tree with Head return new Tree{ Root = TreeNode.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.Create(value); return; } //Find position to insert TreeNode node = Root; node = Descend(value, node)!; if (value.CompareTo(node.Value) < 0) {//Insert to left node.Left = TreeNode.Create(value); return; } //Insert to right node.Right = TreeNode.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>? 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? node = deletionStack.Pop(); //stack to store the items leading up to the value that we will use to replace the node Stack>? 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? 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? Traverse(TraversalType traversalType) { if (Root == default) return default; LinkedList list = LinkedList.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> queue = Queue>.Create(); BreadthFirst(list, queue, Root); break; default: return default; } return list; } private void Inorder(LinkedList list, TreeNode 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 list, TreeNode 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 list, TreeNode 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 list, Queue> queue, TreeNode 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 TreeNode? GetNext(T value, TreeNode? 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>? Find(T value) {//Return true if the item can be found within the tree if (Root == default || Root.Value!.Equals(default)) return default; TreeNode? current = Root; Stack>? stack = Stack>.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 Stack>? Min(TreeNode? 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> stack = Stack>.Create(node); while(true){ if (stack.Peek()!.Left == default) return stack; stack.Push(stack.Peek()!.Left); } } private Stack>? Max(TreeNode? 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> stack = Stack>.Create(node); while(true){ if (stack.Peek()!.Right == default) return stack; stack.Push(stack.Peek()!.Right); } } private TreeNode? Descend(T value, TreeNode? 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? 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 } }