Skip to content

Instantly share code, notes, and snippets.

@pathikrit
Created May 14, 2013 08:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pathikrit/5574521 to your computer and use it in GitHub Desktop.
Save pathikrit/5574521 to your computer and use it in GitHub Desktop.
Interval Map in Java
package com.github.pathikrit.scalgos;
import java.util.Map.Entry;
import java.util.TreeMap;
/**
* Efficient data structure to map values to intervals
* e.g. set(5, 60000, "hello") would set all keys in [5, 60000) to be "hello"
*
* All operations are O(log n) (in practice much faster since n is usually number of segments)
*
* @param <T> The type of data to store
*/
public class IntervalMap<T> {
private final TreeMap<Integer, Segment> segments = new TreeMap<Integer, Segment>();
private class Segment {
final int start, end;
final T value;
Segment(int start, int end, T value) {
this.start = start;
this.end = end;
this.value = value;
// todo: meld here
segments.put(start, this);
}
void destroy() {
segments.remove(start);
}
boolean contains(int x) {
return start <= x && x < end;
}
}
private Segment ceiling(int x) {
return extract(segments.ceilingEntry(x));
}
private Segment floor(int x) {
return extract(segments.floorEntry(x));
}
private Segment extract(Entry<Integer, Segment> e) {
return e != null ? e.getValue() : null;
}
private Segment find(int x) {
final Segment prev = floor(x);
return prev != null && prev.contains(x) ? prev : ceiling(x);
}
/**
* Set all values in [x, y) to be value
*/
public void set(int x, int y, T value) {
assert x < y;
final Segment s = find(x);
if(s == null) {
new Segment(x, y, value);
} else if(x < s.start) {
if(y <= s.start) {
new Segment(x, y, value);
} else if(y < s.end) {
s.destroy();
new Segment(x, y, value);
new Segment(y, s.end, s.value);
} else {
s.destroy();
new Segment(x, s.end, value);
set(s.end, y, value);
}
} else if(x < s.end) {
s.destroy();
new Segment(s.start, x, s.value);
if(y < s.end) {
new Segment(x, y, value);
new Segment(y, s.end, s.value);
} else {
new Segment(x, s.end, value);
set(s.end, y, value);
}
} else {
throw new IllegalStateException();
}
}
/**
* @return value at x
*/
public T get(int x) {
final Segment s = floor(x);
return s != null && s.contains(x) ? s.value : null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment