/// <summary> /// Returns all intervals that overlaps with this interval /// </summary> /// <param name="interval"></param> /// <returns></returns> private List <AsInterval <T> > GetOverlaps(AsIntervalRedBlackTreeNode <AsInterval <T> > current, AsInterval <T> searchInterval, List <AsInterval <T> > result = null) { if (result == null) { result = new List <AsInterval <T> >(); } if (current == null) { return(result); } if (doOverlap(current.Value, searchInterval)) { result.Add(current.Value); } //if left max is greater than search start //then the search interval can occur in left sub tree if (current.Left != null && current.Left.Value.MaxEnd.CompareTo(searchInterval.Start) >= 0) { GetOverlaps(current.Left, searchInterval, result); } //otherwise look in right subtree GetOverlaps(current.Right, searchInterval, result); return(result); }
/// <summary> /// Insert a new Interval /// </summary> /// <param name="newInterval"></param> public void Insert(AsInterval <T> newInterval) { SortInterval(newInterval); RedBlackTree.Insert(newInterval); Count++; }
/// <summary> /// Delete this interval /// </summary> /// <param name="interval"></param> public void Delete(AsInterval <T> interval) { SortInterval(interval); RedBlackTree.Delete(interval); Count--; }
/// <summary> /// Does this interval a overlap with b /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> private bool doOverlap(AsInterval <T> a, AsInterval <T> b) { //lazy reset a.MatchingEndIndex = -1; b.MatchingEndIndex = -1; for (var i = 0; i < a.End.Count; i++) { for (var j = 0; j < b.End.Count; j++) { //a.Start less than b.End and a.End greater than b.Start if (a.Start.CompareTo(b.End[j]) > 0 || a.End[i].CompareTo(b.Start) < 0) { continue; } a.MatchingEndIndex = i; b.MatchingEndIndex = j; return(true); } } return(false); }
/// <summary> /// Swap intervals so that start always appear before end /// </summary> /// <param name="value"></param> private void SortInterval(AsInterval <T> value) { if (value.Start.CompareTo(value.End[0]) > 0) { var tmp = value.End[0]; value.End[0] = value.Start; value.Start = tmp; } }
//O(log(n)) always public void Delete(AsInterval <T> value) { if (Root == null) { throw new Exception("Empty Tree"); } delete(Root, value, false); Count--; }
/// <summary> /// Swap intervals so that start always appear before end /// </summary> /// <param name="value"></param> private void sortInterval(AsInterval <T> value) { if (value.Start.CompareTo(value.End[0]) <= 0) { return; } var tmp = value.End[0]; value.End[0] = value.Start; value.Start = tmp; }
/// <summary> /// returns the index of a matching value in this End range List /// </summary> /// <param name="end"></param> /// <param name="value"></param> /// <returns></returns> private int GetIndex(List <T> end, AsInterval <T> value) { var index = -1; for (int i = 0; i < end.Count; i++) { if (end[i].CompareTo(value.End[0]) == 0) { index = i; } } return(index); }
//O(log(n)) always private AsIntervalRedBlackTreeNode <AsInterval <T> > insert( AsIntervalRedBlackTreeNode <AsInterval <T> > currentNode, AsInterval <T> newNodeValue) { var compareResult = currentNode.Value.CompareTo(newNodeValue); //current node is less than new item if (compareResult < 0) { //no right child if (currentNode.Right == null) { //insert var newNode = new AsIntervalRedBlackTreeNode <AsInterval <T> >(currentNode, newNodeValue); currentNode.Right = newNode; UpdateMax(newNode); BalanceInsertion(newNode); return(newNode); } else { var newNode = insert(currentNode.Right, newNodeValue); return(newNode); } } //current node is greater than new node else if (compareResult > 0) { if (currentNode.Left == null) { //insert var newNode = new AsIntervalRedBlackTreeNode <AsInterval <T> >(currentNode, newNodeValue); currentNode.Left = newNode; UpdateMax(newNode); BalanceInsertion(newNode); return(newNode); } else { var newNode = insert(currentNode.Left, newNodeValue); return(newNode); } } else { currentNode.Value.End.Add(newNodeValue.End[0]); UpdateMax(currentNode); return(currentNode); } }
//O(log(n)) always public void Insert(AsInterval <T> value) { //empty tree if (Root == null) { Root = new AsIntervalRedBlackTreeNode <AsInterval <T> >(null, value); Root.NodeColor = RedBlackTreeNodeColor.Black; UpdateMax(Root); Count++; return; } insert(Root, value); Count++; }
/// <summary> /// Returns an interval that overlaps with this interval /// </summary> /// <param name="interval"></param> /// <returns></returns> private AsInterval <T> GetOverlap(AsIntervalRedBlackTreeNode <AsInterval <T> > current, AsInterval <T> searchInterval) { if (current == null) { return(null); } if (doOverlap(current.Value, searchInterval)) { return(current.Value); } //if left max is greater than search start //then the search interval can occur in left sub tree if (current.Left != null && current.Left.Value.MaxEnd.CompareTo(searchInterval.Start) >= 0) { return(GetOverlap(current.Left, searchInterval)); } //otherwise look in right subtree return(GetOverlap(current.Right, searchInterval)); }
/// <summary> /// does any interval overlaps with this search interval /// </summary> /// <param name="searchInterval"></param> /// <returns></returns> internal bool DoOverlap(AsInterval <T> searchInterval) { SortInterval(searchInterval); return(GetOverlap(RedBlackTree.Root, searchInterval) != null); }
/// <summary> /// Returns an interval in this tree that overlaps with this search interval /// </summary> /// <param name="searchInterval"></param> /// <returns></returns> internal List <AsInterval <T> > GetOverlaps(AsInterval <T> searchInterval) { SortInterval(searchInterval); return(GetOverlaps(RedBlackTree.Root, searchInterval)); }
/// <summary> /// Deletes the node and return a reference to the parent of actual node deleted /// O(log(n)) always /// </summary> /// <param name="node"></param> /// <param name="value"></param> /// <returns></returns> private AsIntervalRedBlackTreeNode <AsInterval <T> > delete(AsIntervalRedBlackTreeNode <AsInterval <T> > node, AsInterval <T> value, bool deleteByStartOnly) { var compareResult = node.Value.CompareTo(value); //node is less than the search value so move right to find the deletion node if (compareResult < 0) { if (node.Right == null) { throw new Exception("Item do not exist"); } return(delete(node.Right, value, deleteByStartOnly)); } //node is less than the search value so move left to find the deletion node else if (compareResult > 0) { if (node.Left == null) { throw new Exception("Item do not exist"); } return(delete(node.Left, value, deleteByStartOnly)); } else { AsIntervalRedBlackTreeNode <AsInterval <T> > nodeToBalance = null; //if not a leaf deletion caused by replacement //of an ancestor deleted with this node if (!deleteByStartOnly) { var index = GetIndex(node.Value.End, value); if (index == -1) { throw new Exception("Interval do not exist"); } if (node.Value.End.Count > 1) { node.Value.End.RemoveAt(index); UpdateMax(node); return(node); } } //node is a leaf node if (node.IsLeaf) { //if color is red, we are good; no need to balance if (node.NodeColor == RedBlackTreeNodeColor.Red) { deleteLeaf(node); UpdateMax(node.Parent); return(node.Parent); } nodeToBalance = handleDoubleBlack(node); deleteLeaf(node); UpdateMax(node.Parent); } else { //case one - right tree is null (move sub tree up) if (node.Left != null && node.Right == null) { nodeToBalance = handleDoubleBlack(node); deleteLeftNode(node); UpdateMax(node.Parent); } //case two - left tree is null (move sub tree up) else if (node.Right != null && node.Left == null) { nodeToBalance = handleDoubleBlack(node); deleteRightNode(node); UpdateMax(node.Parent); } //case three - two child trees //replace the node value with maximum element of left subtree (left max node) //and then delete the left max node else { var index = GetIndex(node.Value.End, value); if (index == -1) { throw new Exception("Interval do not exist"); } //if this is the only element //do regular bst deletion if (node.Value.End.Count == 1 && index == 0) { var maxLeftNode = FindMax(node.Left); node.Value = maxLeftNode.Value; node.Value.MaxEnd = defaultValue.Value; //delete left max node return(delete(node.Left, maxLeftNode.Value, true)); } else { //just remove the end node.Value.End.RemoveAt(index); UpdateMax(node); return(node); } } } var returnNode = nodeToBalance; //handle six cases while (nodeToBalance != null) { nodeToBalance = handleDoubleBlack(nodeToBalance); } return(returnNode); } }
/// <summary> /// Returns an interval in this tree that overlaps with this search interval /// </summary> /// <param name="searchInterval"></param> /// <returns></returns> internal AsInterval <T> GetOverlap(AsInterval <T> searchInterval) { sortInterval(searchInterval); return(getOverlap(redBlackTree.Root, searchInterval)); }