4 package org.adblocktv.tagsserver.utils.rbtree;
7 import org.adblocktv.tagsserver.utils.*;
13 public class IntervalTreeMultiSet<K
extends Comparable, V>
14 extends RedBlackTree<K, IntervalTreeMultiSet<K, V>.IntervalTreeNode>
15 implements Iterable<IntervalTreeMultiSet<K, V>.IntervalTreeNode> {
20 public class IntervalTreeNode
21 extends RedBlackTree<K, IntervalTreeMultiSet<K, V>.IntervalTreeNode>.Node {
26 private Pair<K, K> interval;
41 protected void updatePath() {
42 Node nil = getNilNode();
46 node = node.getParent();
51 protected void updateSingle() {
53 IntervalTreeNode left = getLeftChild().getInternalValue();
54 IntervalTreeNode right = getRightChild().getInternalValue();
58 min = min.compareTo(left.min) < 0 ? min : left.min;
59 max = max.compareTo(left.max) > 0 ? max : left.max;
62 max = max.compareTo(right.max) > 0 ? max : right.max;
67 protected void rotateUpdate() {
75 private IntervalTreeNode(Pair<K, K> interval, V value) {
76 super(interval.a, null);
77 this.interval = interval;
79 setInternalValue(
this);
99 public String toString() {
100 return "{ <" + interval.a +
"," + interval.b +
"> <" + min +
"," + max +
"> "
101 + (getLeftChild() != getNilNode() ? getLeftChild().toString() :
"{ null }")
102 + (getRightChild() != getNilNode() ? getRightChild().toString() :
"{ null }")
110 private class IntervalTreeMultiSetIterator
implements Iterator<IntervalTreeNode> {
112 private Iterator<Node> nodesIterator = nodesIterator();
115 public boolean hasNext() {
116 return nodesIterator.hasNext();
120 public IntervalTreeNode next() {
121 return nodesIterator.next().getInternalValue();
125 public void remove() {
131 private final boolean leftExclusive;
135 private final boolean rightExclusive;
141 private int compareLowHigh(K low, K high) {
142 int result = low.compareTo(high);
143 return result != 0 ? result : (leftExclusive | rightExclusive ? 1 : 0);
149 private int compareLowPoint(K low, K point) {
150 int result = low.compareTo(point);
151 return result != 0 ? result : (leftExclusive ? 1 : 0);
157 private int compareHighPoint(K high, K point) {
158 int result = high.compareTo(point);
159 return result != 0 ? result : (rightExclusive ? -1 : 0);
165 private boolean intersect(Pair<K, K> x, Pair<K, K> y) {
166 return compareLowHigh(x.a, y.b) <= 0 && compareLowHigh(y.a, x.b) <= 0;
172 private boolean intersect(Pair<K, K> x, K point) {
173 return compareLowPoint(x.a, point) <= 0 && compareHighPoint(x.b, point) >= 0;
179 private void searchAll(
181 IntervalTreeNode node,
182 List<IntervalTreeNode> resultNodes) {
184 IntervalTreeNode left = node.getLeftChild().getInternalValue();
185 if (left != null && compareLowHigh(interval.a, left.max) <= 0) {
186 searchAll(interval, left, resultNodes);
189 if (intersect(node.interval, interval)) {
190 resultNodes.add(node);
193 IntervalTreeNode right = node.getRightChild().getInternalValue();
194 if (right != null && compareLowHigh(right.min, interval.b) <= 0) {
195 searchAll(interval, right, resultNodes);
202 private void searchAll(
204 IntervalTreeNode node,
205 List<IntervalTreeNode> resultNodes) {
207 IntervalTreeNode left = node.getLeftChild().getInternalValue();
208 if (left != null && compareHighPoint(left.max, point) >= 0) {
209 searchAll(point, left, resultNodes);
212 if (intersect(node.interval, point)) {
213 resultNodes.add(node);
216 IntervalTreeNode right = node.getRightChild().getInternalValue();
217 if (right != null && compareLowPoint(right.min, point) <= 0) {
218 searchAll(point, right, resultNodes);
228 this.leftExclusive = leftExclusive;
229 this.rightExclusive = rightExclusive;
239 public IntervalTreeNode
add(Pair<K, K> interval, V value) {
240 IntervalTreeNode intervalTreeNode =
new IntervalTreeNode(interval, value);
241 add(intervalTreeNode);
242 return intervalTreeNode;
249 public void remove(IntervalTreeNode intervalTreeNode) {
250 super.remove(intervalTreeNode);
260 public IntervalTreeNode
search(Pair<K, K> interval) {
261 IntervalTreeNode node = getRootNode().getInternalValue();
262 while (node != null && !intersect(node.interval, interval)) {
263 IntervalTreeNode left = node.getLeftChild().getInternalValue();
264 if (left != null && compareLowHigh(interval.a, left.max) <= 0) {
267 node = node.getRightChild().getInternalValue();
280 public IntervalTreeNode
search(K point) {
281 IntervalTreeNode node = getRootNode().getInternalValue();
282 while (node != null && !intersect(node.interval, point)) {
283 IntervalTreeNode left = node.getLeftChild().getInternalValue();
284 if (left != null && compareHighPoint(left.max, point) >= 0) {
287 node = node.getRightChild().getInternalValue();
299 public List<IntervalTreeNode>
searchAll(Pair<K, K> interval) {
300 List<IntervalTreeNode> resultNodes =
new LinkedList();
301 IntervalTreeNode root = getRootNode().getInternalValue();
303 searchAll(interval, root, resultNodes);
315 List<IntervalTreeNode> resultNodes =
new LinkedList();
316 IntervalTreeNode root = getRootNode().getInternalValue();
318 searchAll(point, root, resultNodes);
329 return new IntervalTreeMultiSetIterator();