private static object GetComparerViaReflection(RangeTreeNode<int, RangeItem> rangeTreeNode) { var bindFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static; var comparerFieldInfo = typeof(RangeTreeNode<int, RangeItem>).GetField("_rangeComparer", bindFlags); var comparer = comparerFieldInfo.GetValue(rangeTreeNode); return comparer; }
private static object GetComparerViaReflection(RangeTreeNode <int, RangeItem> rangeTreeNode) { var bindFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static; var comparerFieldInfo = typeof(RangeTreeNode <int, RangeItem>).GetField("rangeComparer", bindFlags); var comparer = comparerFieldInfo.GetValue(rangeTreeNode); return(comparer); }
/// <summary> /// Main build method, build a tree from a list of points, given that the nodes are sorted by last coordinate. /// </summary> /// <param name="rangeTreePoints">Points to store in new range tree. </param> /// <param name="sortingCoordinate">Sorting coordinate of new tree.</param> /// <returns>New balanced range tree.</returns> private RangeTreeNode <TValue> Build(List <ValueTuple <TValue, TValue> > rangeTreePoints, int sortingCoordinate) { if (rangeTreePoints.Count == 0) { return(null); } if (rangeTreePoints.Count == 1) { var node = new RangeTreeNode <TValue>(rangeTreePoints[0], Alpha, sortingCoordinate); return(node); } if (sortingCoordinate == 1) { // another y tree lastOpVisitedNodes += rangeTreePoints.Count; return(CreateBalancedTree(rangeTreePoints)); } // find median, build its other dimension tree var medVal = rangeTreePoints.Median(xComparer); var median = new RangeTreeNode <TValue>(medVal, Alpha, 0); median.OtherDimensionSubtree = new RangeTree <TValue>(Build(new List <(TValue, TValue)>(rangeTreePoints), sortingCoordinate + 1), Alpha); // find nodes with same x-value, set is as middle nodes rangeTreePoints.Remove(medVal); var midsons = FindMiddleSons(rangeTreePoints, medVal, sortingCoordinate); median.SetMiddleSons(midsons); // split nodes by x-value of median var smallerInX = GetSmallerThanPoint(rangeTreePoints, medVal, xComparer); // build sons median.SetLeftSon(Build(smallerInX, sortingCoordinate)); median.SetRightSon(Build(rangeTreePoints, sortingCoordinate)); return(median); }
private static IEnumerable<RangeTreeNode<int, RangeItem>> TraverseNode(RangeTreeNode<int, RangeItem> rangeTreeNode) { var bindFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static; var leftFieldInfo = typeof(RangeTreeNode<int, RangeItem>).GetField("_leftNode", bindFlags); var left = leftFieldInfo.GetValue(rangeTreeNode) as RangeTreeNode<int, RangeItem>; if (left != null) { yield return left; foreach (var node in TraverseNode(left)) { yield return node; } } var rightFieldInfo = typeof(RangeTreeNode<int, RangeItem>).GetField("_rightNode", bindFlags); var right = rightFieldInfo.GetValue(rangeTreeNode) as RangeTreeNode<int, RangeItem>; if (right != null) { yield return right; foreach (var node in TraverseNode(right)) { yield return node; } } }
/// <summary> /// Inserts a new value to tree. /// </summary> /// <param name="newvalue">2D point to be inserted</param> /// <param name="currentCoordinate">Current coordinate to navigate by</param> public void Insert(ValueTuple <TValue, TValue> newvalue, int currentCoordinate) { // for tree validity check //SaveLastState(OperationType.INSERT); lastOpVisitedNodes = 0; if (Root == null) { lastOpVisitedNodes = 1; Root = new RangeTreeNode <TValue>(newvalue, Alpha, currentCoordinate); return; } var comparer = (currentCoordinate == 0) ? xComparer : yComparer; var currentNode = Root; var parent = Root; // find a place for new leaf while (currentNode != null) { lastOpVisitedNodes++; parent = currentNode; if (currentCoordinate == 0) { currentNode.OtherDimensionSubtree.Insert(newvalue, 1); } // greater if (comparer.Compare(newvalue, currentNode.Value) > 0) { currentNode.SubtreeNodesCount++; currentNode = currentNode.Right; } // lesser else if (comparer.Compare(newvalue, currentNode.Value) < 0) { currentNode.SubtreeNodesCount++; currentNode = currentNode.Left; } // equal else { currentNode.AddMiddleSon(new RangeTreeNode <TValue>(newvalue, Alpha, currentCoordinate)); // we are done here, this cannot break the invariant return; } } // add the new leaf RangeTreeNode <TValue> leaf = new RangeTreeNode <TValue>(newvalue, Alpha, currentCoordinate); if (comparer.Compare(parent.Value, newvalue) > 0) { parent.SetLeftSon(leaf); } else { parent.SetRightSon(leaf); } parent.SubtreeNodesCount--; // rebuild the unbalanced trees currentNode = parent; while (currentNode != null) { if (!currentNode.IsBalanced()) { var nodes = QuickSort <TValue> .Sort(currentNode.GetSubtreeValuesInOrder(), yComparer); var rebuild = Build(nodes, currentCoordinate); // for x and y tree lastOpVisitedNodes += (rebuild.SubtreeNodesCount); // we rebuit entire tree if (currentNode.Parent == null) { Root = rebuild; currentNode = rebuild; } else { if (comparer.Compare(currentNode.Parent.Value, rebuild.Value) > 0) { currentNode.Parent.SetLeftSon(rebuild); } else { currentNode.Parent.SetRightSon(rebuild); } } } currentNode = currentNode.Parent; } }
/// <summary> /// Constructor using a given tree (used for Node-Tree conversion). /// </summary> /// <param name="root">Root of new tree.</param> /// <param name="alpha">Alpha of BB-alpha trees implementing range tree</param> public RangeTree(RangeTreeNode <TValue> root, double alpha) { Root = root; Alpha = alpha; }