private void Traversal(BinaryTreeNodeWithSize <T> origin, Stack <T> stack) { if (RandIndex == RandTarget) { return; //reached the random target, stop searching } if (origin.Left != null) { Traversal(origin.Left, stack); } if (RandIndex == RandTarget) { return; } stack.Push(origin.Data); RandIndex++; if (RandIndex == RandTarget) { return; } if (origin.Right != null) { Traversal(origin.Right, stack); } }
private void Insert(T data, BinaryTreeNodeWithSize <T> origin) { int comparisonResult = data.CompareTo(origin.Data); if (comparisonResult == 0) { throw new InvalidOperationException("No duplicate data allowed in BST."); } if (comparisonResult < 0) { if (origin.Left == null) { origin.Left = new BinaryTreeNodeWithSize <T>(data); } else { Insert(data, origin.Left); } } else { if (origin.Right == null) { origin.Right = new BinaryTreeNodeWithSize <T>(data); } else { Insert(data, origin.Right); } } origin.UpdateSize(); }
//Gets a random number by comparing sub-tree sizes to determine the probability //of choosing that node. Worst case takes time equal to the depth of the longest path. public T GetRandom2() { int rIndex = r.Next(1, Count + 1); BinaryTreeNodeWithSize <T> n = root; while (n != null) { if (n.Size == rIndex) { return(n.Data); } if (n.Left != null && rIndex <= n.Left.Size) { n = n.Left; } else { //Left side was not chosen, update our rIndex because we are no longer considering it rIndex -= n.Left?.Size ?? 0; n = n.Right; } } throw new InvalidOperationException("Tree empty!"); }
T Minimum(BinaryTreeNodeWithSize <T> origin) { while (origin.Left != null) { origin = origin.Left; } return(origin.Data); }
public T TraverseToIndex(int index) { BinaryTreeNodeWithSize <T> n = root; var stack = new Stack <T>(); RandTarget = index; RandIndex = -1; Traversal(root, stack); return(stack.Pop()); }
private BinaryTreeNodeWithSize <T> Remove(T data, BinaryTreeNodeWithSize <T> origin) { if (origin == null || data == null) { return(null); } int comparisonResult = data.CompareTo(origin.Data); if (comparisonResult < 0) { if (origin.Left == null) { throw new InvalidOperationException($"Couldn't find {data} to remove!"); } origin.Left = Remove(data, origin.Left); origin.UpdateSize(); return(origin); } if (comparisonResult > 0) { if (origin.Right == null) { throw new InvalidOperationException($"Couldn't find {data} to remove!"); } origin.Right = Remove(data, origin.Right); origin.UpdateSize(); return(origin); } //Match found //If we have two children, replace my data with rights min, then remove starting from right if (origin.Left != null && origin.Right != null) { var minimum = Minimum(origin.Right); origin.Data = minimum; origin.Right = Remove(minimum, origin.Right); origin.UpdateSize(); return(origin); } if (origin.Left == null) { return(origin.Right); } else { return(origin.Left); } }
public RandomElement <T> Insert(T data) { if (data == null) { return(null); } if (root == null) { root = new BinaryTreeNodeWithSize <T>(data); } else { Insert(data, root); } Count++; return(this); }
public bool Find(T data) { BinaryTreeNodeWithSize <T> curr = root; while (curr != null) { int comparisonResult = data.CompareTo(curr.Data); if (comparisonResult < 0) { curr = curr.Left; } else if (comparisonResult > 0) { curr = curr.Right; } else if (comparisonResult == 0) { return(true); } } return(false); }