|
@@ -3,52 +3,74 @@ namespace Invercargill.DataStructures {
|
|
|
|
|
|
public class SortedSeries<T> : Enumerable<T>, Lot<T>, ReadOnlyCollection<T>, Collection<T> {
|
|
|
|
|
|
- private class SeriesNode<T> {
|
|
|
- public bool is_red;
|
|
|
- public Series<T> values { get; private set; }
|
|
|
- public SeriesNode<T> left_child { get; set; }
|
|
|
- public SeriesNode<T> right_child { get; set; }
|
|
|
- public SeriesNode<T> parent { get; set; }
|
|
|
-
|
|
|
- public SeriesNode(T item, SeriesNode<T> nil) {
|
|
|
- is_red = true;
|
|
|
- left_child = nil;
|
|
|
- right_child = nil;
|
|
|
- values = new Series<T>();
|
|
|
- values.add(item);
|
|
|
- }
|
|
|
+ private uint root;
|
|
|
+ private uint nil;
|
|
|
|
|
|
- public SeriesNode.nil() {
|
|
|
- is_red = false;
|
|
|
- left_child = this;
|
|
|
- right_child = this;
|
|
|
- values = new Series<T>();
|
|
|
- }
|
|
|
+ private uint data_count = 0;
|
|
|
+ private uint[] data;
|
|
|
+ private Vector<Series<T>> buckets;
|
|
|
|
|
|
- public T sample() {
|
|
|
- return values.first_or_default();
|
|
|
+ private uint read_left_child(uint index) {
|
|
|
+ return data[index+1];
|
|
|
+ }
|
|
|
+ private uint read_right_child(uint index) {
|
|
|
+ return data[index+2];
|
|
|
+ }
|
|
|
+ private uint? read_parent(uint index) {
|
|
|
+ var value = data[index];
|
|
|
+ if(value == 0){
|
|
|
+ return null;
|
|
|
}
|
|
|
-
|
|
|
- public void add_value(T value) {
|
|
|
- values.add(value);
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ private bool read_is_red(uint index) {
|
|
|
+ return data[index+4] == 1;
|
|
|
+ }
|
|
|
+ private void write_left_child(uint index, uint value) {
|
|
|
+ data[index+1] = value;
|
|
|
+ }
|
|
|
+ private void write_right_child(uint index, uint value) {
|
|
|
+ data[index+2] = value;
|
|
|
+ }
|
|
|
+ private void write_parent(uint index, uint? value) {
|
|
|
+ if(value == null) {
|
|
|
+ data[index] = 0;
|
|
|
+ return;
|
|
|
}
|
|
|
-
|
|
|
- // public void remove_all_values_where (PredicateDelegate<T> predicate) {
|
|
|
- // values = values.where(v => !predicate(v)).to_buffer();
|
|
|
- // }
|
|
|
+ data[index] = value;
|
|
|
+ }
|
|
|
+ private void write_is_red(uint index, bool value) {
|
|
|
+ data[index+4] = value ? 1 : 0;
|
|
|
+ }
|
|
|
+ private void add_to_bucket(uint index, T item) {
|
|
|
+ buckets[data[index+3]].add(item);
|
|
|
+ }
|
|
|
+ private Tracker<T> get_bucket_tracker(uint index) {
|
|
|
+ return buckets[data[index+3]].get_tracker();
|
|
|
+ }
|
|
|
+ private T get_bucket_sample(uint index) {
|
|
|
+ print(@"$(buckets[data[index+3]].count()) in buk $index with $n_items\n");
|
|
|
+ return buckets[data[index+3]].first_or_default();
|
|
|
+ }
|
|
|
+ private uint create_node() {
|
|
|
+ var index = data_count;
|
|
|
+ data_count += 5;
|
|
|
+ // data.add_all(Invercargill.range(0, 5).select<uint>(i => 0));
|
|
|
+ var bucket_index = buckets.count();
|
|
|
+ data[index+3] = bucket_index;
|
|
|
+ buckets.add(new Series<T>());
|
|
|
+ return index;
|
|
|
}
|
|
|
|
|
|
- private SeriesNode<T> root;
|
|
|
- private SeriesNode<T> nil;
|
|
|
private RWLock rw_lock;
|
|
|
- private Series<SeriesNode<T>> node_refs;
|
|
|
private CompareDelegate<T> comparitor;
|
|
|
private int n_items;
|
|
|
|
|
|
public SortedSeries(owned CompareDelegate<T>? comparitor = null) {
|
|
|
- nil = new SeriesNode<T>.nil();
|
|
|
- node_refs = new Series<SeriesNode<T>>();
|
|
|
- node_refs.add(nil);
|
|
|
+ buckets = new Vector<Series<T>>();
|
|
|
+ // data = new Vector<uint>();
|
|
|
+ data = new uint[15000];
|
|
|
+ nil = create_node();
|
|
|
root = nil;
|
|
|
rw_lock = RWLock();
|
|
|
n_items = 0;
|
|
@@ -74,30 +96,30 @@ namespace Invercargill.DataStructures {
|
|
|
rw_lock.writer_lock();
|
|
|
n_items++;
|
|
|
|
|
|
- SeriesNode<T>? parent = null;
|
|
|
- SeriesNode<T> current = root;
|
|
|
+ uint? parent = null;
|
|
|
+ uint current = root;
|
|
|
int cmp = 0;
|
|
|
|
|
|
while(current != nil) {
|
|
|
parent = current;
|
|
|
- cmp = comparitor(item, current.sample());
|
|
|
+ cmp = comparitor(item, get_bucket_sample(current));
|
|
|
if(cmp == 0) {
|
|
|
// Add to node, has no effect on tree
|
|
|
- current.add_value(item);
|
|
|
+ add_to_bucket(current, item);
|
|
|
rw_lock.writer_unlock();
|
|
|
return;
|
|
|
}
|
|
|
if(cmp < 0) {
|
|
|
- current = current.left_child;
|
|
|
+ current = read_left_child(current);
|
|
|
}
|
|
|
else {
|
|
|
- current = current.right_child;
|
|
|
+ current = read_right_child(current);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- var new_node = new SeriesNode<T> (item, nil);
|
|
|
- node_refs.add(new_node);
|
|
|
- new_node.parent = parent;
|
|
|
+ var new_node = create_node();
|
|
|
+ add_to_bucket(new_node, item);
|
|
|
+ write_parent(new_node, parent);
|
|
|
if(parent == null) {
|
|
|
root = new_node;
|
|
|
}
|
|
@@ -107,63 +129,71 @@ namespace Invercargill.DataStructures {
|
|
|
assert_not_reached ();
|
|
|
}
|
|
|
else if(cmp < 0) {
|
|
|
- parent.left_child = new_node;
|
|
|
+ write_left_child(parent, new_node);
|
|
|
}
|
|
|
else {
|
|
|
- parent.right_child = new_node;
|
|
|
+ write_right_child(parent, new_node);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(new_node.parent == null) {
|
|
|
- new_node.is_red = false;
|
|
|
+ if(read_parent(new_node) == null) {
|
|
|
+ write_is_red(new_node, false);
|
|
|
}
|
|
|
- else if(new_node.parent.parent != null) {
|
|
|
+ else if(read_parent(read_parent(new_node)) != null) {
|
|
|
fix_insert(new_node);
|
|
|
}
|
|
|
|
|
|
rw_lock.writer_unlock();
|
|
|
}
|
|
|
|
|
|
- private void fix_insert(SeriesNode<T> new_node) {
|
|
|
- var node = new_node;
|
|
|
- while(node != root && node.parent.is_red) {
|
|
|
- if(node.parent == node.parent.parent.left_child) {
|
|
|
- var uncle = node.parent.parent.right_child;
|
|
|
- if(uncle.is_red) {
|
|
|
- node.parent.is_red = false;
|
|
|
- uncle.is_red = false;
|
|
|
- node.parent.parent.is_red = true;
|
|
|
- node = node.parent.parent;
|
|
|
+ private void fix_insert(uint z) {
|
|
|
+ uint node = z;
|
|
|
+
|
|
|
+ while(node != root && read_is_red(read_parent(node))) {
|
|
|
+ uint parent = read_parent(node);
|
|
|
+ uint grandparent = read_parent(parent);
|
|
|
+
|
|
|
+ if(parent == read_left_child(grandparent)) {
|
|
|
+ uint uncle = read_right_child(grandparent);
|
|
|
+ if(uncle != nil && read_is_red(uncle)) {
|
|
|
+ write_is_red(parent, false);
|
|
|
+ write_is_red(uncle, false);
|
|
|
+ write_is_red(grandparent, true);
|
|
|
+ node = grandparent;
|
|
|
continue;
|
|
|
}
|
|
|
- if(node == node.parent.right_child) {
|
|
|
- node = node.parent;
|
|
|
+ if(node == read_right_child(parent)) {
|
|
|
+ node = parent;
|
|
|
rotate_left(node);
|
|
|
+ parent = read_parent(node);
|
|
|
+ grandparent = read_parent(parent);
|
|
|
}
|
|
|
- node.parent.is_red = false;
|
|
|
- node.parent.parent.is_red = true;
|
|
|
- rotate_right (node.parent.parent);
|
|
|
- }
|
|
|
- else {
|
|
|
- var uncle = node.parent.parent.left_child;
|
|
|
- if(uncle.is_red) {
|
|
|
- node.parent.is_red = false;
|
|
|
- uncle.is_red = false;
|
|
|
- node.parent.parent.is_red = true;
|
|
|
- node = node.parent.parent;
|
|
|
+ write_is_red(parent, false);
|
|
|
+ write_is_red(grandparent, true);
|
|
|
+ rotate_right(grandparent);
|
|
|
+ } else {
|
|
|
+ uint uncle = read_left_child(grandparent);
|
|
|
+ if(uncle != nil && read_is_red(uncle)) {
|
|
|
+ write_is_red(parent, false);
|
|
|
+ write_is_red(uncle, false);
|
|
|
+ write_is_red(grandparent, true);
|
|
|
+ node = grandparent;
|
|
|
continue;
|
|
|
}
|
|
|
- if(node == node.parent.left_child) {
|
|
|
- node = node.parent;
|
|
|
+ if(node == read_left_child(parent)) {
|
|
|
+ node = parent;
|
|
|
rotate_right(node);
|
|
|
+ parent = read_parent(node);
|
|
|
+ grandparent = read_parent(parent);
|
|
|
}
|
|
|
- node.parent.is_red = false;
|
|
|
- node.parent.parent.is_red = true;
|
|
|
- rotate_left(node.parent.parent);
|
|
|
+ write_is_red(parent, false);
|
|
|
+ write_is_red(grandparent, true);
|
|
|
+ rotate_left(grandparent);
|
|
|
}
|
|
|
}
|
|
|
- root.is_red = false;
|
|
|
+ write_is_red(root, false);
|
|
|
}
|
|
|
+
|
|
|
public void remove_first_where (PredicateDelegate<T> predicate) {
|
|
|
assert_not_reached ();
|
|
|
}
|
|
@@ -175,111 +205,110 @@ namespace Invercargill.DataStructures {
|
|
|
}
|
|
|
|
|
|
|
|
|
- private void rotate_left(SeriesNode<T> x) {
|
|
|
- var y = x.right_child;
|
|
|
- x.right_child = y.left_child;
|
|
|
- if(y.left_child != nil)
|
|
|
- y.left_child.parent = x;
|
|
|
- y.parent = x.parent;
|
|
|
- if(x.parent == null)
|
|
|
+ private void rotate_left(uint x) {
|
|
|
+ uint y = read_right_child(x);
|
|
|
+ write_right_child(x, read_left_child(y));
|
|
|
+ if(read_left_child(y) != nil)
|
|
|
+ write_parent(read_left_child(y), x);
|
|
|
+ write_parent(y, read_parent(x));
|
|
|
+ if(read_parent(x) == null)
|
|
|
root = y;
|
|
|
- else if(x.parent.left_child == x)
|
|
|
- x.parent.left_child = y;
|
|
|
+ else if(x == read_left_child(read_parent(x)))
|
|
|
+ write_left_child(read_parent(x), y);
|
|
|
else
|
|
|
- x.parent.right_child = y;
|
|
|
- y.left_child = x;
|
|
|
- x.parent = y;
|
|
|
+ write_right_child(read_parent(x), y);
|
|
|
+ write_left_child(y, x);
|
|
|
+ write_parent(x, y);
|
|
|
}
|
|
|
|
|
|
- private void rotate_right(SeriesNode<T> x) {
|
|
|
- var y = x.left_child;
|
|
|
- x.left_child = y.right_child;
|
|
|
- if(y.right_child != nil)
|
|
|
- y.right_child.parent = x;
|
|
|
- y.parent = x.parent;
|
|
|
- if(x.parent == null)
|
|
|
+ private void rotate_right(uint x) {
|
|
|
+ uint y = read_left_child(x);
|
|
|
+ write_left_child(x, read_right_child(y));
|
|
|
+ if(read_right_child(y) != nil)
|
|
|
+ write_parent(read_right_child(y), x);
|
|
|
+ write_parent(y, read_parent(x));
|
|
|
+ if(read_parent(x) == null)
|
|
|
root = y;
|
|
|
- else if(x.parent.right_child == x)
|
|
|
- x.parent.right_child = y;
|
|
|
+ else if(x == read_right_child(read_parent(x)))
|
|
|
+ write_right_child(read_parent(x), y);
|
|
|
else
|
|
|
- x.parent.left_child = y;
|
|
|
- y.right_child = x;
|
|
|
- x.parent = y;
|
|
|
+ write_left_child(read_parent(x), y);
|
|
|
+ write_right_child(y, x);
|
|
|
+ write_parent(x, y);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private class TreeTracker<T> : Tracker<T> {
|
|
|
|
|
|
- SeriesNode<T> node;
|
|
|
- SeriesNode<T>? next_node;
|
|
|
- SortedSeries<T> series;
|
|
|
- Tracker<T> values;
|
|
|
+ private SortedSeries<T> series;
|
|
|
+ private uint current_node;
|
|
|
+ private uint? next_node;
|
|
|
+ private Tracker<T>? values;
|
|
|
|
|
|
public TreeTracker(SortedSeries<T> series) {
|
|
|
- print("New tracker!\n");
|
|
|
this.series = series;
|
|
|
- node = series.root;
|
|
|
- while(node.left_child != series.nil) {
|
|
|
- node = node.left_child;
|
|
|
+
|
|
|
+ // Find the leftmost node (smallest value)
|
|
|
+ current_node = series.root;
|
|
|
+ if(current_node != series.nil) {
|
|
|
+ while(series.read_left_child(current_node) != series.nil) {
|
|
|
+ current_node = series.read_left_child(current_node);
|
|
|
+ }
|
|
|
+ values = series.get_bucket_tracker(current_node);
|
|
|
}
|
|
|
- values = node.values.get_tracker();
|
|
|
+
|
|
|
find_next_node();
|
|
|
}
|
|
|
|
|
|
- public override bool has_next () {
|
|
|
- return values.has_next() || next_node != null;
|
|
|
+ public override bool has_next() {
|
|
|
+ return (values != null && values.has_next()) || next_node != null;
|
|
|
}
|
|
|
- public override T get_next () {
|
|
|
- if(values.has_next()) {
|
|
|
+
|
|
|
+ public override T get_next() {
|
|
|
+ if(values != null && values.has_next()) {
|
|
|
return values.get_next();
|
|
|
}
|
|
|
- node = next_node;
|
|
|
- values = node.values.get_tracker();
|
|
|
- var result = values.get_next();
|
|
|
+
|
|
|
+ if(next_node == null) {
|
|
|
+ assert_not_reached();
|
|
|
+ }
|
|
|
+
|
|
|
+ current_node = next_node;
|
|
|
+ values = series.get_bucket_tracker(current_node);
|
|
|
+ T result = values.get_next();
|
|
|
+
|
|
|
find_next_node();
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
private void find_next_node() {
|
|
|
- // next_node = null;
|
|
|
- // if(node.right_child != series.nil) {
|
|
|
- // next_node = node.right_child;
|
|
|
- // while(next_node.left_child != series.nil) {
|
|
|
- // next_node = next_node.left_child;
|
|
|
- // }
|
|
|
- // }
|
|
|
- // else if(node.parent == null) {
|
|
|
- // next_node = null;
|
|
|
- // }
|
|
|
- // else if(node.parent.left_child == node) {
|
|
|
- // next_node = node.parent;
|
|
|
- // }
|
|
|
- // else if(node.parent.parent.right_child == node.parent) {
|
|
|
- // next_node = null;
|
|
|
- // }
|
|
|
- // else {
|
|
|
- // next_node = node.parent.parent;
|
|
|
- // }
|
|
|
next_node = null;
|
|
|
- if (node == null) return;
|
|
|
- // standard inorder successor:
|
|
|
- if (node.right_child != series.nil) {
|
|
|
- var n = node.right_child;
|
|
|
- while (n.left_child != series.nil)
|
|
|
- n = n.left_child;
|
|
|
+ if(current_node == series.nil) return;
|
|
|
+
|
|
|
+ uint n = current_node;
|
|
|
+
|
|
|
+ // If there is a right child, go there then all the way left
|
|
|
+ uint right = series.read_right_child(n);
|
|
|
+ if(right != series.nil) {
|
|
|
+ n = right;
|
|
|
+ while(series.read_left_child(n) != series.nil) {
|
|
|
+ n = series.read_left_child(n);
|
|
|
+ }
|
|
|
next_node = n;
|
|
|
return;
|
|
|
}
|
|
|
- var n = node;
|
|
|
- var p = n.parent;
|
|
|
- while (p != null && n == p.right_child) {
|
|
|
- n = p;
|
|
|
- p = p.parent;
|
|
|
+
|
|
|
+ // Walk up the tree until we find a node that is a left child
|
|
|
+ uint? parent = series.read_parent(n);
|
|
|
+ while(parent != null && n == series.read_right_child(parent)) {
|
|
|
+ n = parent;
|
|
|
+ parent = series.read_parent(n);
|
|
|
}
|
|
|
- next_node = p; // could be null (end)
|
|
|
- }
|
|
|
|
|
|
+ next_node = parent; // could be null if we've reached the end
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|