/// <summary> /// Initializes a tree with a list of items to be added. /// </summary> public RangeTree(IEnumerable <IInterval <T> > items, IComparer <IInterval <T> > rangeComparer = null) { this._rangeComparer = rangeComparer ?? Comparer <IInterval <T> > .Default; this._items = items != null?items.ToList() : new List <IInterval <T> >(); this._root = new RangeTreeNode <T>(this._items, rangeComparer); this._isInSync = true; this._autoRebuild = true; }
/// <summary> /// Rebuilds the tree if it is out of sync. /// </summary> public void Rebuild() { if (this._isInSync) { return; } this._root = new RangeTreeNode <T>(this._items, this._rangeComparer); this._isInSync = true; }
/// <summary> /// Initializes a node with a list of items, builds the sub tree. /// </summary> /// <param name="items">Data to include in this node.</param> /// <param name="rangeComparer">The comparer used to compare two items.</param> public RangeTreeNode(IEnumerable <IInterval <T> > items, IComparer <IInterval <T> > rangeComparer = null) { rangeComparer = rangeComparer ?? Comparer <IInterval <T> > .Default; // No items? nothing to do if (items == null || !items.Any()) { return; } // first, find the median var endPoints = new List <T>(); foreach (var o in items) { var range = o; endPoints.Add(range.Min.Value); endPoints.Add(range.Max.Value); } endPoints.Sort(); // the median is used as center value this._center = endPoints[endPoints.Count / 2]; this._items = new List <IInterval <T> >(); var left = new List <IInterval <T> >(); var right = new List <IInterval <T> >(); // iterate over all items // if the range of an item is completely left of the center, add it to the left items // if it is on the right of the center, add it to the right items // otherwise (range overlaps the center), add the item to this node's items foreach (var o in items) { var range = o; if (range.Max.Value.CompareTo(this._center) < 0) { left.Add(o); } else if (range.Min.Value.CompareTo(this._center) > 0) { right.Add(o); } else { this._items.Add(o); } } // sort the items, this way the query is faster later on if (this._items.Count > 0) { this._items.Sort(rangeComparer); } else { this._items = null; } // create left and right nodes, if there are any items if (left.Count > 0) { this._leftNode = new RangeTreeNode <T>(left); } if (right.Count > 0) { this._rightNode = new RangeTreeNode <T>(right); } }
/// <summary> /// Clears the tree (removes all items). /// </summary> public void Clear() { this._root = new RangeTreeNode <T>(this._rangeComparer); this._items = new List <IInterval <T> >(); this._isInSync = true; }