intervaltree: support for single-unit intervals

The structure is still not perfect and needs revising in some edge cases where unneeded child nodes are left instead of being added in the parent
treemaps-queues-iteration
EmaMaker 2022-08-11 16:05:56 +02:00
parent 83beccc48c
commit 9c6cf30120
2 changed files with 13 additions and 19 deletions

View File

@ -41,11 +41,11 @@ public class Interval {
}
public boolean fullyLeftOf(Interval i) {
return this.high < i.low;
return this.high <= i.low;
}
public boolean fullyRightOf(Interval i) {
return this.low > i.high;
return this.low >= i.high;
}
public boolean partiallyContainsLeft(Interval i) {
@ -58,6 +58,6 @@ public class Interval {
@Override
public String toString() {
return "[" + low + ", " + high + "]";
return "[" + low + ", " + high + ")";
}
}

View File

@ -24,12 +24,9 @@ public class IntervalTree<V> {
// For what we're doing, when we add new values that (partially) overlap old
// ones, we can't have the old ones laying around, so intervals need to be
// readjusted accordingly
// For a normal interval tree, there's no need no check for partial overrides
// Also, no values can be shared from one node to another (no limits in common, e.g. one node has the high limit that is the same as the low limit of its right child)
public TreeNode insertNode(TreeNode currentNode, TreeNode newNode) {
if (!newNode.interval.isValid()) return null;
if (currentNode == null)
return newNode;
if (currentNode == null) return newNode;
// System.out.println(currentNode.interval.toString() +", "+
// newNode.interval.toString());
@ -45,13 +42,13 @@ public class IntervalTree<V> {
if (newNode.value.equals(currentNode.value)) {
currentNode.interval = newNode.interval;
} else {
TreeNode newLeftNode = new TreeNode(new Interval(newNode.interval.low, currentNode.interval.low - 1),
newNode.value, currentNode.left, null);
TreeNode newLeftNode = new TreeNode(new Interval(newNode.interval.low, currentNode.interval.low), newNode.value, currentNode.left, null);
newNode.setInterval(currentNode.interval.high + 1, newNode.interval.high);
newNode.setInterval(currentNode.interval.high, newNode.interval.high);
newNode.setRight(currentNode.right);
// Important! otherwhise already existing nodes will node by replaced
// Important! otherwhise already existing nodes will node by
// replaced
currentNode.value = newNode.value;
currentNode.setLeft(newLeftNode);
@ -66,27 +63,24 @@ public class IntervalTree<V> {
if (newNode.value.equals(currentNode.value)) return currentNode;
if (currentNode.interval.low < newNode.interval.low)
newNode.setLeft(new TreeNode(new Interval(currentNode.interval.low, newNode.interval.low - 1),
currentNode.value, currentNode.left, null));
newNode.setLeft(new TreeNode(new Interval(currentNode.interval.low, newNode.interval.low), currentNode.value, currentNode.left, null));
else newNode.setLeft(null);
if (newNode.interval.high < currentNode.interval.high)
newNode.setRight(new TreeNode(new Interval(newNode.interval.high + 1, currentNode.interval.high),
currentNode.value, null, currentNode.right));
else
newNode.setRight(null);
newNode.setRight(new TreeNode(new Interval(newNode.interval.high, currentNode.interval.high), currentNode.value, null, currentNode.right));
else newNode.setRight(null);
return newNode;
} else if (newNode.interval.partiallyContainsLeft(currentNode.interval)) {
currentNode.setInterval(currentNode.interval.low, newNode.interval.low - 1);
currentNode.setInterval(currentNode.interval.low, newNode.interval.low);
newNode.setLeft(currentNode);
constrainIntervals(currentNode, currentNode.interval);
return newNode;
} else if (newNode.interval.partiallyContainsRight(currentNode.interval)) {
currentNode.setInterval(newNode.interval.high + 1, currentNode.interval.high);
currentNode.setInterval(newNode.interval.high, currentNode.interval.high);
newNode.setRight(currentNode);
constrainIntervals(currentNode, currentNode.interval);