diff --git a/src/structure/collections/hash-set.ts b/src/structure/collections/hash-set.ts
index 8cf25df5585d98566e939beeedf6345de4e86d55..2d13b16c6b15d3837ab29a4720e85372f68ab0a9 100644
--- a/src/structure/collections/hash-set.ts
+++ b/src/structure/collections/hash-set.ts
@@ -42,6 +42,7 @@ class HashSetImpl<T> implements SetLike<T> {
 
     constructor(private getHash: (v: T) => any, private areEqual: (a: T, b: T) => boolean) { }
 }
+// TODO: add implementations with multilevel hashing support?
 
 function HashSet<T>(getHash: (v: T) => any, areEqual: (a: T, b: T) => boolean): SetLike<T> {
     return new HashSetImpl<T>(getHash, areEqual);
diff --git a/src/structure/collections/linked-index.ts b/src/structure/collections/linked-index.ts
index 0f40f2d0ddafa491cf1a6ef1833c4e20a86379a3..0433ba03de4d1d5b51acab4b9368ac777c1b68ad 100644
--- a/src/structure/collections/linked-index.ts
+++ b/src/structure/collections/linked-index.ts
@@ -38,7 +38,7 @@ class LinkedIndexImpl implements LinkedIndex {
     }
 
     has(i: number) {
-        return this.prev[i] >= 0 || this.next[i] >= 0;
+        return this.prev[i] >= 0 || this.next[i] >= 0 || this.head === i;
     }
 
     constructor(size: number) {
diff --git a/src/structure/collections/range-set.ts b/src/structure/collections/range-set.ts
index 6543f94287b773d374c525ec7bbcde3a4fdb86b5..8043407324b83c08bdb6fbf9060959e9aecd7015 100644
--- a/src/structure/collections/range-set.ts
+++ b/src/structure/collections/range-set.ts
@@ -32,6 +32,7 @@ namespace RangeSet {
         if (size > 2) hash = 31 * hash + a.elementAt(size >> 1);
         return hash;
     }
+    // TODO: possibly add more hash functions to allow for multilevel hashing.
 
     export function areEqual(a: RangeSet, b: RangeSet) {
         if (a === b) return true;
diff --git a/src/structure/spec/collections.spec.ts b/src/structure/spec/collections.spec.ts
index 848ec48037aa608e95d1f276fcc220b6885427d2..0b5276b3665731197d24d2ac6d4ea53264b16ce1 100644
--- a/src/structure/spec/collections.spec.ts
+++ b/src/structure/spec/collections.spec.ts
@@ -8,6 +8,7 @@ import Iterator from '../collections/iterator'
 import IntPair from '../collections/int-pair'
 import * as Sort from '../collections/sort'
 import RangeSet from '../collections/range-set'
+import LinkedIndex from '../collections/linked-index'
 
 describe('basic iterators', () => {
     function check<T>(name: string, iter: Iterator<T>, expected: T[]) {
@@ -102,7 +103,7 @@ describe('qsort-dual array', () => {
     const cmp: Sort.Comparer<typeof data> = (data, i, j) => data.xs[i] - data.xs[j];
     const swap: Sort.Swapper<typeof data> = (data, i, j) => { Sort.arraySwap(data.xs, i, j); Sort.arraySwap(data.ys, i, j); }
     const clone = (d: typeof data) => ({ xs: [...d.xs], ys: [...d.ys] })
- 
+
     function test(name: string, src: typeof data, randomize: boolean) {
         it(name, () => {
             // [ 3, 1, 6, 4, 4, 6, 4, 2, 6, 1, 2, 3 ];
@@ -185,4 +186,47 @@ describe('range set', () => {
     testEq('intersect RR2', RangeSet.intersect(range, RangeSet.ofRange(3, 5)), [3, 4]);
     testEq('intersect RA', RangeSet.intersect(range, arr), [1, 3]);
     testEq('intersect AA', RangeSet.intersect(arr, RangeSet.ofSortedArray([2, 3, 4, 6, 7])), [3, 6]);
+});
+
+describe('linked-index', () => {
+    it('initial state', () => {
+        const index = LinkedIndex(2);
+        expect(index.head).toBe(0);
+        expect(index.has(0)).toBe(true);
+        expect(index.has(1)).toBe(true);
+    });
+
+    it('singleton', () => {
+        const index = LinkedIndex(1);
+        expect(index.head).toBe(0);
+        expect(index.has(0)).toBe(true);
+        index.remove(0);
+        expect(index.head).toBe(-1);
+        expect(index.has(0)).toBe(false);
+    });
+
+    it('remove 0', () => {
+        const index = LinkedIndex(2);
+        index.remove(0);
+        expect(index.head).toBe(1);
+        expect(index.has(0)).toBe(false);
+        expect(index.has(1)).toBe(true);
+    });
+
+    it('remove 1', () => {
+        const index = LinkedIndex(2);
+        index.remove(1);
+        expect(index.head).toBe(0);
+        expect(index.has(0)).toBe(true);
+        expect(index.has(1)).toBe(false);
+    });
+
+    it('remove 01', () => {
+        const index = LinkedIndex(2);
+        index.remove(0);
+        index.remove(1);
+        expect(index.head).toBe(-1);
+        expect(index.has(0)).toBe(false);
+        expect(index.has(1)).toBe(false);
+    });
 });
\ No newline at end of file