/// <summary> /// Creates balanced tree from a sorted list. /// </summary> /// <param name="rangeTreePoints">Points to store in the tree</param> /// <returns>New (Y) range tree.</returns> private RangeTreeNode <TValue> CreateBalancedTree(List <ValueTuple <TValue, TValue> > rangeTreePoints) { if (rangeTreePoints.Count == 0) { return(null); } var medVal = rangeTreePoints[rangeTreePoints.Count / 2]; var median = new RangeTreeNode <TValue>(medVal, Alpha, 1); if (rangeTreePoints.Count == 1) { return(median); } rangeTreePoints.Remove(medVal); var midsons = FindMiddleSons(rangeTreePoints, medVal, 1); median.SetMiddleSons(midsons); var smallerInY = GetSmallerThanPoint(rangeTreePoints, medVal, yComparer); // build sons median.SetLeftSon(CreateBalancedTree(smallerInY)); median.SetRightSon(CreateBalancedTree(rangeTreePoints)); return(median); }
/// <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); }