private void QueryRange(IntervalTreeNode intervalTreeNode, Int64 start, Int64 end, List <T> results) { for (int i = intervalTreeNode.first; i <= intervalTreeNode.last; i++) { var entry = m_Entries[i]; if (end >= entry.intervalStart && start < entry.intervalEnd) { results.Add(entry.item); } } if (intervalTreeNode.center == kCenterUnknown) { return; } if (intervalTreeNode.left != kInvalidNode && start < intervalTreeNode.center) { QueryRange(m_Nodes[intervalTreeNode.left], start, end, results); } if (intervalTreeNode.right != kInvalidNode && end > intervalTreeNode.center) { QueryRange(m_Nodes[intervalTreeNode.right], start, end, results); } }
private void Query(IntervalTreeNode intervalTreeNode, Int64 value, List <T> results) { for (int i = intervalTreeNode.first; i <= intervalTreeNode.last; i++) { var entry = m_Entries[i]; if (value >= entry.intervalStart && value < entry.intervalEnd) { results.Add(entry.item); } } if (intervalTreeNode.center == kCenterUnknown) { return; } if (intervalTreeNode.left != kInvalidNode && value < intervalTreeNode.center) { Query(m_Nodes[intervalTreeNode.left], value, results); } if (intervalTreeNode.right != kInvalidNode && value > intervalTreeNode.center) { Query(m_Nodes[intervalTreeNode.right], value, results); } }
private int Rebuild(int start, int end) { IntervalTreeNode intervalTreeNode = new IntervalTreeNode(); // minimum size, don't subdivide int count = end - start + 1; if (count < kMinNodeSize) { intervalTreeNode = new IntervalTreeNode() { center = kCenterUnknown, first = start, last = end, left = kInvalidNode, right = kInvalidNode }; m_Nodes.Add(intervalTreeNode); return(m_Nodes.Count - 1); } var min = Int64.MaxValue; var max = Int64.MinValue; for (int i = start; i <= end; i++) { var o = m_Entries[i]; min = Math.Min(min, o.intervalStart); max = Math.Max(max, o.intervalEnd); } var center = (max + min) / 2; intervalTreeNode.center = center; // first pass, put every thing left of center, left int x = start; int y = end; while (true) { while (x <= end && m_Entries[x].intervalEnd < center) { x++; } while (y >= start && m_Entries[y].intervalEnd >= center) { y--; } if (x > y) { break; } var nodeX = m_Entries[x]; var nodeY = m_Entries[y]; m_Entries[y] = nodeX; m_Entries[x] = nodeY; } intervalTreeNode.first = x; // second pass, put every start passed the center right y = end; while (true) { while (x <= end && m_Entries[x].intervalStart <= center) { x++; } while (y >= start && m_Entries[y].intervalStart > center) { y--; } if (x > y) { break; } var nodeX = m_Entries[x]; var nodeY = m_Entries[y]; m_Entries[y] = nodeX; m_Entries[x] = nodeY; } intervalTreeNode.last = y; // reserve a place m_Nodes.Add(new IntervalTreeNode()); int index = m_Nodes.Count - 1; intervalTreeNode.left = kInvalidNode; intervalTreeNode.right = kInvalidNode; if (start < intervalTreeNode.first) { intervalTreeNode.left = Rebuild(start, intervalTreeNode.first - 1); } if (end > intervalTreeNode.last) { intervalTreeNode.right = Rebuild(intervalTreeNode.last + 1, end); } m_Nodes[index] = intervalTreeNode; return(index); }