diff options
| author | Terry Truong <terry06890@gmail.com> | 2022-10-18 12:04:17 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2022-10-18 12:04:17 +1100 |
| commit | 610995001f7f58110e4ff73b68df005a7280a79e (patch) | |
| tree | 66c91c6cd78837da153d49203690a7aa50d300c7 /src/rbtree.ts | |
| parent | 15035fe65e7dd54db83337da3d2b055d8bb668e9 (diff) | |
Use shallowRef for event tree
- Fixes 'saved is null' errors
- De-lint rbtree.ts
- Add rbtree_shallow_copy(), for triggering changes upon modifying the
eventTree (using triggerRef doesn't work)
Diffstat (limited to 'src/rbtree.ts')
| -rw-r--r-- | src/rbtree.ts | 83 |
1 files changed, 46 insertions, 37 deletions
diff --git a/src/rbtree.ts b/src/rbtree.ts index b857086..8422dec 100644 --- a/src/rbtree.ts +++ b/src/rbtree.ts @@ -40,7 +40,7 @@ class Iterator<T> { // otherwise, returns next node next(): T | null{ if (this._cursor === null) { - let root = this._tree._root; + const root = this._tree._root; if (root !== null) { this._minNode(root); } @@ -68,12 +68,12 @@ class Iterator<T> { } } return this._cursor !== null ? this._cursor.data : null; - }; + } // if null-iterator, returns last node // otherwise, returns previous node prev(): T | null { if(this._cursor === null) { - let root = this._tree._root; + const root = this._tree._root; if(root !== null) { this._maxNode(root); } @@ -98,21 +98,21 @@ class Iterator<T> { } } return this._cursor !== null ? this._cursor.data : null; - }; + } _minNode(start: Node<T>) { while(start.left !== null) { this._ancestors.push(start); start = start.left; } this._cursor = start; - }; + } _maxNode(start: Node<T>) { while(start.right !== null) { this._ancestors.push(start); start = start.right; } this._cursor = start; - }; + } } export class RBTree<T> { @@ -133,7 +133,7 @@ export class RBTree<T> { find(data: T): T | null{ let res = this._root; while (res !== null) { - let c = this._comparator(data, res.data); + const c = this._comparator(data, res.data); if(c === 0) { return res.data; } @@ -146,9 +146,9 @@ export class RBTree<T> { // returns iterator to node if found, null otherwise findIter(data: T): Iterator<T> | null { let res = this._root; - let iter = this.iterator(); + const iter = this.iterator(); while(res !== null) { - let c = this._comparator(data, res.data); + const c = this._comparator(data, res.data); if(c === 0) { iter._cursor = res; return iter; @@ -159,14 +159,14 @@ export class RBTree<T> { } } return null; - }; + } // Returns an iterator to the tree node at or immediately after the item lowerBound(item: T): Iterator<T> { let cur = this._root; - let iter = this.iterator(); - let cmp = this._comparator; + const iter = this.iterator(); + const cmp = this._comparator; while(cur !== null) { - let c = cmp(item, cur.data); + const c = cmp(item, cur.data); if(c === 0) { iter._cursor = cur; return iter; @@ -184,16 +184,16 @@ export class RBTree<T> { } iter._ancestors.length = 0; return iter; - }; + } // Returns an iterator to the tree node immediately after the item upperBound(item: T): Iterator<T> { - let iter = this.lowerBound(item); - let cmp = this._comparator; + const iter = this.lowerBound(item); + const cmp = this._comparator; while(iter.data() !== null && cmp(iter.data()!, item) === 0) { iter.next(); } return iter; - }; + } // returns null if tree is empty min(): T | null { let res = this._root; @@ -204,7 +204,7 @@ export class RBTree<T> { res = res.left; } return res.data; - }; + } // returns null if tree is empty max(): T | null { let res = this._root; @@ -215,30 +215,32 @@ export class RBTree<T> { res = res.right; } return res.data; - }; + } // returns a null iterator // call next() or prev() to point to an element iterator() { return new Iterator(this); - }; + } // calls cb on each node's data, in order each(cb: (x: T) => boolean) { - let it=this.iterator(), data; + const it = this.iterator(); + let data: T | null; while((data = it.next()) !== null) { if(cb(data) === false) { return; } } - }; + } // calls cb on each node's data, in reverse order reach(cb: (x: T) => boolean) { - var it=this.iterator(), data; + const it=this.iterator(); + let data: T | null; while((data = it.prev()) !== null) { if(cb(data) === false) { return; } } - }; + } // returns true if inserted, false if duplicate insert(data: T): boolean { let ret = false; @@ -249,7 +251,7 @@ export class RBTree<T> { this.size++; } else { - let head = new Node(undefined) as Node<T>; // fake tree root + const head = new Node(undefined) as Node<T>; // fake tree root let dir = false; let last = false; // setup @@ -275,7 +277,7 @@ export class RBTree<T> { } // fix red violation if(is_red(node) && is_red(p)) { - let dir2 = ggp.right === gp; + const dir2 = ggp.right === gp; if(node === p!.get_child(last)) { ggp.set_child(dir2, single_rotate(gp!, !last)); } @@ -283,7 +285,7 @@ export class RBTree<T> { ggp.set_child(dir2, double_rotate(gp!, !last)); } } - let cmp = this._comparator(node.data, data); + const cmp = this._comparator(node.data, data); // stop if found if(cmp === 0) { break; @@ -304,13 +306,13 @@ export class RBTree<T> { // make root black this._root!.red = false; return ret; - }; + } // returns true if removed, false if not found remove(data: T): boolean { if(this._root === null) { return false; } - let head = new Node(undefined) as Node<T>; // fake tree root + const head = new Node(undefined) as Node<T>; // fake tree root let node = head; node.right = this._root; let p: Node<T> | null = null; // parent @@ -318,12 +320,12 @@ export class RBTree<T> { let found: Node<T> | null = null; // found item let dir = true; while(node.get_child(dir) !== null) { - let last = dir; + const last = dir; // update helpers gp = p; p = node; node = node.get_child(dir)!; - let cmp = this._comparator(data, node.data); + const cmp = this._comparator(data, node.data); dir = cmp > 0; // save found node if (cmp === 0) { @@ -332,12 +334,12 @@ export class RBTree<T> { // push the red node down if (!is_red(node) && !is_red(node.get_child(dir))) { if(is_red(node.get_child(!dir))) { - let sr = single_rotate(node, dir); + const sr = single_rotate(node, dir); p.set_child(last, sr); p = sr; } else if(!is_red(node.get_child(!dir))) { - let sibling = p.get_child(!last); + const sibling = p.get_child(!last); if(sibling !== null) { if(!is_red(sibling.get_child(!last)) && !is_red(sibling.get_child(last))) { // color flip @@ -346,7 +348,7 @@ export class RBTree<T> { node.red = true; } else { - let dir2 = gp!.right === p; + const dir2 = gp!.right === p; if(is_red(sibling.get_child(last))) { gp!.set_child(dir2, double_rotate(p, last)); } @@ -354,7 +356,7 @@ export class RBTree<T> { gp!.set_child(dir2, single_rotate(p, last)); } // ensure correct coloring - let gpc = gp!.get_child(dir2)!; + const gpc = gp!.get_child(dir2)!; gpc.red = true; node.red = true; gpc.left!.red = false; @@ -376,7 +378,7 @@ export class RBTree<T> { this._root.red = false; } return found !== null; - }; + } } function is_red<T>(node: Node<T> | null): boolean { @@ -384,7 +386,7 @@ function is_red<T>(node: Node<T> | null): boolean { } function single_rotate<T>(root: Node<T>, dir: boolean): Node<T> { - let save = root.get_child(!dir)!; + const save = root.get_child(!dir)!; root.set_child(!dir, save.get_child(dir)); save.set_child(dir, root); root.red = true; @@ -396,3 +398,10 @@ function double_rotate<T>(root: Node<T>, dir: boolean): Node<T> { root.set_child(!dir, single_rotate(root.get_child(!dir)!, !dir)); return single_rotate(root, dir); } + +export function rbtree_shallow_copy<T>(tree: RBTree<T>): RBTree<T> { + const newTree = new RBTree(tree._comparator); + newTree._root = tree._root; + newTree.size = tree.size; + return newTree; +} |
