using C_.Datastructures.BinaryTree; using C_.Datastructures.Stack; 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 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(); TreeNode? parent = 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) {//If there are values to the right TreeNode? replacementNode = replacementStack.Pop(); node.Value = replacementNode!.Value; //Remove the node that we have taken the value from if (replacementStack.Peek() != default) {//If the parent is not the node that we replaced replacementStack.Pop()!.Left = replacementNode.Right; }else{//If the parent is the node what we replaced node.Right = replacementNode.Right; } }else{ //Parent's relation needs to be set to null as there are no greater values if (node.Value!.CompareTo(parent!.Value) < 0) {//Item being deleted is the left child parent.Left = default; } //Item being deleted is the right value parent.Right = default; } Count--; return true; } 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(Traverse(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? Traverse(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 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, Traverse(value, current)); if (node == null) { return current; } return node; } } }