|
@@ -4,7 +4,8 @@ namespace Invercargill {
|
|
|
|
|
|
public class Set<T> : Collection<T> {
|
|
|
|
|
|
- private Dictionary<T, T> dict;
|
|
|
+ private Vector<T> items;
|
|
|
+ private Vector<Series<int>> buckets;
|
|
|
private HashDelegate<T> hash_func;
|
|
|
private EqualityDelegate<T> equal_func;
|
|
|
|
|
@@ -17,18 +18,32 @@ namespace Invercargill {
|
|
|
}
|
|
|
|
|
|
private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
|
|
|
- hash_func = value_hash_func;
|
|
|
- equal_func = value_equal_func;
|
|
|
- dict = new Dictionary<T, T>(value_hash_func, value_equal_func);
|
|
|
+ hash_func = value_hash_func ?? Operators.hash<T>();
|
|
|
+ equal_func = value_equal_func ?? Operators.equality<T>();
|
|
|
+ items = new Vector<T>();
|
|
|
+ buckets = new Vector<Series<int>>();
|
|
|
+ buckets.add_all(range(0, 4096).select<Series<int>>(i => new Series<int>()));
|
|
|
}
|
|
|
|
|
|
|
|
|
public override Tracker<T> get_tracker () {
|
|
|
- return dict.get_keys().get_tracker();
|
|
|
+ return items.get_tracker();
|
|
|
}
|
|
|
|
|
|
public override void add (T item) {
|
|
|
- dict[item] = item;
|
|
|
+ var index = (int)bucket_for(item);
|
|
|
+ var bucket = buckets.get_or_default(index);
|
|
|
+ if(bucket != null && bucket.any(i => equal_func(i, item)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if(bucket == null) {
|
|
|
+ bucket = new Series<int>();
|
|
|
+ buckets[index] = bucket;
|
|
|
+ }
|
|
|
+
|
|
|
+ var item_index = items.count();
|
|
|
+ items.add(item);
|
|
|
+ bucket.add(item_index);
|
|
|
}
|
|
|
|
|
|
public override void add_all (Enumerable<T> items) {
|
|
@@ -54,7 +69,17 @@ namespace Invercargill {
|
|
|
}
|
|
|
|
|
|
public new T? find(T item) {
|
|
|
- return dict.get_or_default(item);
|
|
|
+ var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
+ if(bucket == null)
|
|
|
+ return null;
|
|
|
+
|
|
|
+ foreach (var index in bucket) {
|
|
|
+ var result = items[index];
|
|
|
+ if(equal_func(result, item)) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
|
|
@@ -62,26 +87,41 @@ namespace Invercargill {
|
|
|
}
|
|
|
|
|
|
public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
|
|
|
- dict.remove_where(predicate);
|
|
|
+ items.where(predicate).iterate(remove);
|
|
|
}
|
|
|
|
|
|
public void remove(T item) {
|
|
|
- dict.clear(item);
|
|
|
+ var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
+ if(bucket == null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ foreach (var index in bucket) {
|
|
|
+ var result = items[index];
|
|
|
+ if(equal_func(result, item)) {
|
|
|
+ bucket.remove_first_where(i => i == index);
|
|
|
+ items.remove(index);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void remove_all(Enumerable<T> items) {
|
|
|
- items.iterate(dict.clear);
|
|
|
+ items.iterate(remove);
|
|
|
}
|
|
|
|
|
|
public void remove_except(Enumerable<T> items) {
|
|
|
var other = items.to_set(hash_func, equal_func);
|
|
|
- dict.remove_where(i => !other.has(i));
|
|
|
+ remove_where(i => !other.has(i));
|
|
|
}
|
|
|
|
|
|
public bool has(T item) {
|
|
|
- return dict.has(item);
|
|
|
+ var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
+ return bucket != null && bucket.any(i => equal_func(i, item));
|
|
|
}
|
|
|
|
|
|
+ private uint bucket_for(T item) {
|
|
|
+ var hash = hash_func(item);
|
|
|
+ return hash % buckets.count();
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
}
|