|
@@ -5,18 +5,31 @@ namespace Invercargill.DataStructures {
|
|
|
|
|
|
private class SeriesNode<T> {
|
|
private class SeriesNode<T> {
|
|
public bool is_red;
|
|
public bool is_red;
|
|
- public Series<T> values;
|
|
|
|
- public SeriesNode<T>? left_child;
|
|
|
|
- public SeriesNode<T>? right_child;
|
|
|
|
- public SeriesNode<T>? parent;
|
|
|
|
|
|
+ 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) {
|
|
|
|
|
|
+ public SeriesNode(T item, SeriesNode<T> nil) {
|
|
is_red = true;
|
|
is_red = true;
|
|
|
|
+ left_child = nil;
|
|
|
|
+ right_child = nil;
|
|
values = new Series<T>();
|
|
values = new Series<T>();
|
|
values.add(item);
|
|
values.add(item);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public SeriesNode.nil() {
|
|
|
|
+ is_red = false;
|
|
|
|
+ left_child = this;
|
|
|
|
+ right_child = this;
|
|
|
|
+ values = new Series<T>();
|
|
|
|
+ }
|
|
|
|
+
|
|
public T sample() {
|
|
public T sample() {
|
|
|
|
+ assert_nonnull (this);
|
|
|
|
+ assert_nonnull (left_child);
|
|
|
|
+ assert_nonnull (right_child);
|
|
|
|
+ assert_nonnull (values);
|
|
return values.first_or_default();
|
|
return values.first_or_default();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -24,27 +37,38 @@ namespace Invercargill.DataStructures {
|
|
values.add(value);
|
|
values.add(value);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ ~SeriesNode() {
|
|
|
|
+ if(values.count() > 0)
|
|
|
|
+ print(@"Byebye $((int)sample())\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
// public void remove_all_values_where (PredicateDelegate<T> predicate) {
|
|
// public void remove_all_values_where (PredicateDelegate<T> predicate) {
|
|
// values = values.where(v => !predicate(v)).to_buffer();
|
|
// values = values.where(v => !predicate(v)).to_buffer();
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
|
|
|
|
private SeriesNode<T> root;
|
|
private SeriesNode<T> root;
|
|
|
|
+ private SeriesNode<T> nil;
|
|
|
|
+ private HashSet<SeriesNode<T>> nodes;
|
|
private RWLock rw_lock;
|
|
private RWLock rw_lock;
|
|
private CompareDelegate<T> comparitor;
|
|
private CompareDelegate<T> comparitor;
|
|
private int n_items;
|
|
private int n_items;
|
|
|
|
|
|
public SortedSeries(owned CompareDelegate<T>? comparitor = null) {
|
|
public SortedSeries(owned CompareDelegate<T>? comparitor = null) {
|
|
|
|
+ nil = new SeriesNode<T>.nil();
|
|
|
|
+ nodes = new HashSet<SeriesNode<T>> ();
|
|
|
|
+ nodes.add(nil);
|
|
|
|
+ root = nil;
|
|
rw_lock = RWLock();
|
|
rw_lock = RWLock();
|
|
n_items = 0;
|
|
n_items = 0;
|
|
this.comparitor = (owned)comparitor ?? Operators.comparison<T>();
|
|
this.comparitor = (owned)comparitor ?? Operators.comparison<T>();
|
|
}
|
|
}
|
|
|
|
|
|
public override Tracker<T> get_tracker () {
|
|
public override Tracker<T> get_tracker () {
|
|
- if(root == null) {
|
|
|
|
|
|
+ if(root == nil) {
|
|
return empty<T>().get_tracker();
|
|
return empty<T>().get_tracker();
|
|
}
|
|
}
|
|
- return new TreeTracker<T>(root);
|
|
|
|
|
|
+ return new TreeTracker<T>(this);
|
|
}
|
|
}
|
|
public override int? peek_count () {
|
|
public override int? peek_count () {
|
|
return n_items;
|
|
return n_items;
|
|
@@ -56,65 +80,56 @@ namespace Invercargill.DataStructures {
|
|
|
|
|
|
public void add (T item) {
|
|
public void add (T item) {
|
|
// Get lock and update count of items
|
|
// Get lock and update count of items
|
|
- print("Get lock and update count of items\n");
|
|
|
|
rw_lock.writer_lock();
|
|
rw_lock.writer_lock();
|
|
n_items++;
|
|
n_items++;
|
|
|
|
|
|
- // Set root if it doesn't exist
|
|
|
|
- print("Set root if it doesn't exist\n");
|
|
|
|
- if(root == null) {
|
|
|
|
- root = new SeriesNode<T>(item);
|
|
|
|
- root.is_red = false;
|
|
|
|
- rw_lock.writer_unlock();
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ SeriesNode<T>? parent = null;
|
|
|
|
+ SeriesNode<T> current = root;
|
|
|
|
+ int cmp = 0;
|
|
|
|
|
|
- // Find leaf node
|
|
|
|
- print("Find leaf node\n");
|
|
|
|
- var node = root;
|
|
|
|
- int cmp;
|
|
|
|
- while(true) {
|
|
|
|
- cmp = comparitor(item, node.sample());
|
|
|
|
- print(@"CMP=$cmp; item=$((int)item); sample=$((int)node.sample());\n");
|
|
|
|
|
|
+ while(current != nil) {
|
|
|
|
+ parent = current;
|
|
|
|
+ cmp = comparitor(item, current.sample());
|
|
if(cmp == 0) {
|
|
if(cmp == 0) {
|
|
- // No change to tree, simply add the value to this node
|
|
|
|
- print("No change to tree, simply add the value to this node\n");
|
|
|
|
- node.add_value (item);
|
|
|
|
|
|
+ // Add to node, has no effect on tree
|
|
|
|
+ current.add_value(item);
|
|
rw_lock.writer_unlock();
|
|
rw_lock.writer_unlock();
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- if(cmp > 0) {
|
|
|
|
- if(node.right_child == null)
|
|
|
|
- break;
|
|
|
|
- node = node.right_child;
|
|
|
|
- }
|
|
|
|
if(cmp < 0) {
|
|
if(cmp < 0) {
|
|
- if(node.left_child == null)
|
|
|
|
- break;
|
|
|
|
- node = node.left_child;
|
|
|
|
|
|
+ current = current.left_child;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ current = current.right_child;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Make new node, replacing the leaf
|
|
|
|
- print("Make new node, replacing the leaf\n");
|
|
|
|
- var new_node = new SeriesNode<T>(item);
|
|
|
|
- new_node.parent = node;
|
|
|
|
- if(node == null) {
|
|
|
|
|
|
+ var new_node = new SeriesNode<T> (item, nil);
|
|
|
|
+ nodes.add(new_node);
|
|
|
|
+ new_node.parent = parent;
|
|
|
|
+ if(parent == null) {
|
|
root = new_node;
|
|
root = new_node;
|
|
- new_node.is_red = true;
|
|
|
|
- }
|
|
|
|
- else if(cmp > 0) {
|
|
|
|
- node.right_child = new_node;
|
|
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- node.left_child = new_node;
|
|
|
|
|
|
+ if(cmp == 0) {
|
|
|
|
+ print("Does this actually happen?\n");
|
|
|
|
+ assert_not_reached ();
|
|
|
|
+ }
|
|
|
|
+ else if(cmp < 0) {
|
|
|
|
+ parent.left_child = new_node;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ parent.right_child = new_node;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Balance the tree
|
|
|
|
- print("Balance the tree\n");
|
|
|
|
- if(new_node.parent?.parent != null) {
|
|
|
|
- fix_insert (new_node);
|
|
|
|
|
|
+
|
|
|
|
+ if(new_node.parent == null) {
|
|
|
|
+ new_node.is_red = false;
|
|
}
|
|
}
|
|
|
|
+ else if(new_node.parent.parent != null) {
|
|
|
|
+ fix_insert(new_node);
|
|
|
|
+ }
|
|
|
|
+
|
|
rw_lock.writer_unlock();
|
|
rw_lock.writer_unlock();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -123,10 +138,10 @@ namespace Invercargill.DataStructures {
|
|
while(node != root && node.parent.is_red) {
|
|
while(node != root && node.parent.is_red) {
|
|
if(node.parent == node.parent.parent.left_child) {
|
|
if(node.parent == node.parent.parent.left_child) {
|
|
var uncle = node.parent.parent.right_child;
|
|
var uncle = node.parent.parent.right_child;
|
|
- if(uncle != null && uncle.is_red) {
|
|
|
|
|
|
+ if(uncle.is_red) {
|
|
node.parent.is_red = false;
|
|
node.parent.is_red = false;
|
|
uncle.is_red = false;
|
|
uncle.is_red = false;
|
|
- uncle.parent.is_red = true;
|
|
|
|
|
|
+ node.parent.parent.is_red = true;
|
|
node = node.parent.parent;
|
|
node = node.parent.parent;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
@@ -140,10 +155,10 @@ namespace Invercargill.DataStructures {
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
var uncle = node.parent.parent.left_child;
|
|
var uncle = node.parent.parent.left_child;
|
|
- if(uncle != null && uncle.is_red) {
|
|
|
|
|
|
+ if(uncle.is_red) {
|
|
node.parent.is_red = false;
|
|
node.parent.is_red = false;
|
|
uncle.is_red = false;
|
|
uncle.is_red = false;
|
|
- uncle.parent.is_red = true;
|
|
|
|
|
|
+ node.parent.parent.is_red = true;
|
|
node = node.parent.parent;
|
|
node = node.parent.parent;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
@@ -157,7 +172,6 @@ namespace Invercargill.DataStructures {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
root.is_red = false;
|
|
root.is_red = false;
|
|
-
|
|
|
|
}
|
|
}
|
|
public void remove_first_where (PredicateDelegate<T> predicate) {
|
|
public void remove_first_where (PredicateDelegate<T> predicate) {
|
|
assert_not_reached ();
|
|
assert_not_reached ();
|
|
@@ -173,7 +187,7 @@ namespace Invercargill.DataStructures {
|
|
private void rotate_left(SeriesNode<T> x) {
|
|
private void rotate_left(SeriesNode<T> x) {
|
|
var y = x.right_child;
|
|
var y = x.right_child;
|
|
x.right_child = y.left_child;
|
|
x.right_child = y.left_child;
|
|
- if(y.left_child != null)
|
|
|
|
|
|
+ if(y.left_child != nil)
|
|
y.left_child.parent = x;
|
|
y.left_child.parent = x;
|
|
y.parent = x.parent;
|
|
y.parent = x.parent;
|
|
if(x.parent == null)
|
|
if(x.parent == null)
|
|
@@ -189,7 +203,7 @@ namespace Invercargill.DataStructures {
|
|
private void rotate_right(SeriesNode<T> x) {
|
|
private void rotate_right(SeriesNode<T> x) {
|
|
var y = x.left_child;
|
|
var y = x.left_child;
|
|
x.left_child = y.right_child;
|
|
x.left_child = y.right_child;
|
|
- if(y.right_child != null)
|
|
|
|
|
|
+ if(y.right_child != nil)
|
|
y.right_child.parent = x;
|
|
y.right_child.parent = x;
|
|
y.parent = x.parent;
|
|
y.parent = x.parent;
|
|
if(x.parent == null)
|
|
if(x.parent == null)
|
|
@@ -206,12 +220,14 @@ namespace Invercargill.DataStructures {
|
|
|
|
|
|
SeriesNode<T> node;
|
|
SeriesNode<T> node;
|
|
SeriesNode<T>? next_node;
|
|
SeriesNode<T>? next_node;
|
|
|
|
+ SortedSeries<T> series;
|
|
Tracker<T> values;
|
|
Tracker<T> values;
|
|
|
|
|
|
- public TreeTracker(SeriesNode<T> root) {
|
|
|
|
|
|
+ public TreeTracker(SortedSeries<T> series) {
|
|
print("New tracker!\n");
|
|
print("New tracker!\n");
|
|
- node = root;
|
|
|
|
- while(node.left_child != null) {
|
|
|
|
|
|
+ this.series = series;
|
|
|
|
+ node = series.root;
|
|
|
|
+ while(node.left_child != series.nil) {
|
|
node = node.left_child;
|
|
node = node.left_child;
|
|
}
|
|
}
|
|
values = node.values.get_tracker();
|
|
values = node.values.get_tracker();
|
|
@@ -233,25 +249,42 @@ namespace Invercargill.DataStructures {
|
|
}
|
|
}
|
|
|
|
|
|
private void find_next_node() {
|
|
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;
|
|
next_node = null;
|
|
- if(node.right_child != null) {
|
|
|
|
- next_node = node.right_child;
|
|
|
|
- while(next_node.left_child != null) {
|
|
|
|
- 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;
|
|
|
|
|
|
+ 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;
|
|
|
|
+ next_node = n;
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- else {
|
|
|
|
- next_node = node.parent.parent;
|
|
|
|
|
|
+ var n = node;
|
|
|
|
+ var p = n.parent;
|
|
|
|
+ while (p != null && n == p.right_child) {
|
|
|
|
+ n = p;
|
|
|
|
+ p = p.parent;
|
|
}
|
|
}
|
|
|
|
+ next_node = p; // could be null (end)
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|