Data structures, data types, and algorithms with superpowers! 💪😎
implemented in JavaScript.
"JavaScript's missing data structures, data types, and algorithms!" - Mark Twain
$ yarn add @clarketm/super
$ npm install @clarketm/super --save
// 1. import `each` module `independently`
import { Array, Map, Queue, Trie, ... } from "@clarketm/super";
let array = new Array([1, 2]);
...
// 2. import `all` modules under a `namespace`
import Super from "@clarketm/super";
let array = new Super.Array([1, 2]);
...
import { Array } from "@clarketm/super";
let array = new Array([0, 1, 2, 3]); // [0, 1, 2, 3]
// Use any built-in Array methods:
array.push(4); // [0, 1, 2, 3, 4]
// Use custom methods (e.g. `flat`):
let array = new Array([[[1]], [[2]], [[3]]]);
array.flat(2); // [1, 2, 3]
// sorting
array.bubbleSort(); // [0, 1, 2, 3]
array.insertionSort(); // [0, 1, 2, 3]
array.mergeSort(); // [0, 1, 2, 3]
array.quickSort(); // [0, 1, 2, 3]
array.selectionSort(); // [0, 1, 2, 3]
// sorting (w/ comparator)
array.bubbleSort((a, b) => b - a); // [3, 2, 1, 0]
array.insertionSort((a, b) => b - a); // [3, 2, 1, 0]
array.mergeSort((a, b) => b - a); // [3, 2, 1, 0]
array.quickSort((a, b) => b - a); // [3, 2, 1, 0]
array.selectionSort((a, b) => b - a); // [3, 2, 1, 0]
import { AVLTree } from "@clarketm/super";
let tree = new AVLTree([1, 2, 3, 4, 5, 6, 7, 8]);
// Â Â Â Â Â Â 4 -> root
// Â Â Â Â Â / \
// 2 6
// / \ / \
// 1 3 5 7
// \
// 8
//
tree.root; // AVLTreeNode { _value: 5, ... }
tree.height; // 1
tree.insert(9);
// Â Â Â Â Â Â 4 -> root
// Â Â Â Â Â / \
// 2 6
// / \ / \
// 1 3 5 8
// / \
// 7 9
//
tree.balanced; // true
tree.search(3); // AVLTreeNode { _value: 3, ... }
tree.remove(9);
// Â Â Â Â Â Â 4 -> root
// Â Â Â Â Â / \
// 2 6
// / \ / \
// 1 3 5 8
// /
// 7
//
// Use a custom comparator to determine tree hierarchy
// string length (ascending) comparator
let tree = new AVLTree(["green", "red", "blue"], (a, b) => a.length - b.length);
// Â Â Â Â Â "blue" -> root
// Â Â Â Â Â / \
// "red" "green"
//
tree.findMax().value; // "green"
import { BinaryTree } from "@clarketm/super";
let tree = new BinaryTree([5, 3, 7, 2, 8, 4, 6, 1]);
// Â Â Â Â Â Â 5 -> root
// Â Â Â Â Â / \
// 3 7
// / \ / \
// 2 4 6 8
// /
// 1
tree.root; // BinaryTreeNode { _value: 5, ... }
tree.height; // 1
tree.insert(9);
// Â Â Â Â Â Â 5 -> root
// Â Â Â Â Â / \
// 3 7
// / \ / \
// 2 4 6 8
// / \
// 1 9 -> node inserted
//
tree.search(3); // BinaryTreeNode { _value: 3, ... }
tree.remove(9);
// Â Â Â Â Â Â 5 -> root
// Â Â Â Â Â / \
// 3 7
// / \ / \
// 2 4 6 8
// /
// 1 -> node removed
//
// Use a custom comparator to determine tree hierarchy
// string length (ascending) comparator
let tree = new BinaryTree(["green", "red", "blue"], (a, b) => a.length - b.length);
// Â Â Â Â Â "blue" -> root
// Â Â Â Â Â / \
// "red" "green"
//
tree.findMax().value; // "green"
import { Heap } from "@clarketm/super";
// Max / Min (default) heap comparators
let { MAX, MIN } = Heap.HeapType;
let minHeap = new Heap([3, 7, 2, 5], MIN);
// Â Â Â Â Â Â 2 -> min
// Â Â Â Â Â / \
// 5 3
// /
// 7
//
minHeap.min; // 2
minHeap.insert(8); // 5 : new size
// Â Â Â Â Â Â 2 -> min
// Â Â Â Â Â / \
// 5 3
// / \
// 7 8 -> node inserted
//
let min = minHeap.deleteMin(); // 2
// Â Â Â Â Â Â 3 -> min
// Â Â Â Â Â / \
// 5 8
// /
// 7
//
let maxHeap = new Heap([3, 7, 2, 5], MAX);
// Â Â Â Â Â Â 7 -> max
// Â Â Â Â Â / \
// 5 3
// /
// 2
//
maxHeap.max; // 7
maxHeap.isEmpty(); // false
maxHeap.clear();
maxHeap.size; // 0
import { LinkedList } from "@clarketm/super";
let list = new LinkedList([1, 3, 5, 7]);
// 1 <-> 3 <-> 5 <-> 7
list.size; // 4
list.head; // ListNode { _value: 1, ... }
list.tail; // ListNode { _value: 7, ... }
list.insert(1, 100);
// node inserted at pos: 1
// ^
// 1 <-> 100 <-> 3 <-> 5 <-> 7
list.append(99);
// node inserted at tail
// ^
// Â 1 Â <-> Â 100 Â <-> Â 3 Â <-> Â 5 Â <-> Â 7 <-> 99
list.remove(-1);
// node removed from tail
// ^
// Â 1 Â <-> Â 100 Â <-> Â 3 Â <-> Â 5 Â <-> Â 7
list.toArray(); // [ 1, 100, 3, 5, 7 ]
import { Map } from "@clarketm/super";
let map = new Map([["a", 1], ["b", 2], ["c", 3]]); // Map { 'a' => 1, 'b' => 2, 'c' => 3 }
// Use any built-in Map methods:
map.get("c"); // 3
// Use custom methods (e.g. `setDefault`):
// note: `setDefault` is similar to get(), but will set key to a defaultValue if the key is not in Map.
let item = map.setDefault("c", 3);
item; // 3
map; // Map { 'a' => 1, 'b' => 2, 'c' => 3 }
let item = map.setDefault("d", 4);
item; // 4
map; // Map { 'a' => 1, 'b' => 2, 'c' => 3 'd' => 4 }
import { Object } from "@clarketm/super";
let object = new Object({ a: 1, b: true, c: 4 }); // Object { a: 1, b: true, c: 4 }
// Use any built-in Object methods:
Object.keys(object); // [ 'a', 'b', 'c' ]
// Use custom methods (e.g. `clone`):
// note: `clone` will create a deep copy of the object.
let clone = object.clone(); // Object { a: 1, b: true, c: 4 }
Object.is(object, clone); // false
import { PriorityQueue } from "@clarketm/super";
// note: a PriorityQueue can be constructed from either a Map, Array of Arrays, Array of Objects, or Array w/ custom comparator.
// Map
let pq = new PriorityQueue(new Map([[100, "high"], [0, "low"]]));
// Array of Arrays
let pq = new PriorityQueue([[100, "high"], [0, "low"]]);
// Array of Objects
let pq = new PriorityQueue([{ value: "high", priority: 100 }, { value: "low", priority: 0 }]);
// Array w/ custom comparator
let pq = new PriorityQueue(["high", "low"], (a, b) => a.length > b.length);
let pq = new PriorityQueue([[100, "high"], [50, "medium"], [0, "low"]]);
// highest priority lowest priority
// ^ ^
// | Â "high" Â | Â "medium" Â | Â "low" Â |
// | Â (100) Â Â | Â Â (50) Â Â | Â Â (0) |
//
pq.size; // 3
pq.high; // QueueNode { _value: 'super high', _priority: 1000, ... }
pq.low; // QueueNode { _value: 'low', _priority: 0, ... }
pq.isEmpty(); // false
pq.insert("super high", 1000); // 4 : new size
// highest priority lowest priority
// ^ ^
// | Â "super high" Â | Â "high" Â | Â "medium" Â | Â "low" Â |
// | Â (1000) Â | Â (100) Â Â | Â Â (50) Â Â | Â Â (0) |
//
pq.deleteHigh(); // QueueNode { _value: 'super high', _priority: 1000, ... }
// highest priority lowest priority
// ^ ^
// | Â "high" Â | Â "medium" Â | Â "low" Â |
// | Â (100) Â Â | Â Â (50) Â Â | Â Â (0) |
//
pq.deleteLow(); // QueueNode { _value: 'low', _priority: 0, ... }
// highest priority lowest priority
// ^ ^
// | Â "high" Â | Â "medium" Â |
// | Â (100) Â Â | Â Â (50) Â Â |
//
pq.clear();
pq.size; // 0
import { Queue } from "@clarketm/super";
let queue = new Queue([2, 4, 6, 8]);
// front rear
// ^ ^
// | 2 | 4 | 6 | 8 |
queue.size; // 4
queue.front; // 2
queue.rear; // 8
queue.isEmpty(); // false
queue.enqueue(10); // 5 : new size
// front rear
// ^ ^
// | 2 | 4 | 6 | 8 | 10 |
queue.dequeue(); // 2 : dequeued item
// front rear
// ^ ^
// | 4 | 6 | 8 | 10 |
queue.clear();
queue.size; // 0
import { Set } from "@clarketm/super";
let setA = new Set([1, 2, 3]); // Set { 1, 2, 3 }
let setB = new Set([2, 3, 4]); // Set { 2, 3, 4 }
// Use any built-in Set methods:
setA.has(1); // true
// Use custom methods:
// `isSubset`
setA.isSubset(setB); // false
// `isSuperset`
setA.isSuperset(setB); // false
// `isDisjoint`
setA.isDisjoint(setB); // false
// `union`
setA.union(setB); // Set { 1, 2, 3, 4 }
// `intersection`
setA.intersection(setB); // Set { 2, 3 }
// `difference`
setA.difference(setB); // Set { 1 }
// `symmetricDifference`
setA.symmetricDifference(setB); // Set { 1, 4 }
import { Trie } from "@clarketm/super";
let trie = new Trie(["me", "men", "go"]);
// Â Â Â Â Â Â root
// Â Â Â Â Â / \
// 'm' 'g'
// / \
// Â $ <- 'e' Â Â 'o' -> $
// /
// $ <- 'n'
//
// $: denotes a complete word
//
trie.root; // TrieNode { _char: √, ... }
trie.insert("met");
// Â Â Â Â Â Â root
// Â Â Â Â Â / \
// 'm' 'g'
// / \
// Â $ <- 'e' Â Â 'o' -> $
// / \
// $ <- 'n' 't' -> $
//
// $: denotes a complete word
//
// `word` search w/ `contains`
trie.contains("me"); // true
// `prefix` search w/ `startsWith`
trie.startsWith("m"); // true
// Return a full Match object w/ `search`
trie.search("men");
// Match object
// {
// query: 'men',
// matchedChars: 3,
// isMatch: true,
// isCompleteWord: true,
// node: TrieNode { ... }
// }
trie.remove("go");
// Â Â Â Â Â Â root
// Â Â Â Â Â /
// 'm'
// /
// Â $ <- 'e'
// / \
// $ <- 'n' 't' -> $
//
// $: denotes a complete word
//
import { bubbleSort } from "@clarketm/super";
// General usage
// ascending
let sortedArray = bubbleSort([4, 3, 8, 1]); // [1, 3, 4, 8]
// Custom comparator
// descending
let sortedArray = bubbleSort([4, 3, 8, 1], (a, b) => b - a); // [8, 4, 3, 1]
// ascending (string length)
let sortedArray = bubbleSort(["111", "1", "11"], (a, b) => a.length - b.length); // ["1", "11", "111"]
// descending (string length)
let sortedArray = bubbleSort(["111", "1", "11"], (a, b) => b.length - a.length); // ["111", "11", "1"]
import { insertionSort } from "@clarketm/super";
// General usage
// ascending
let sortedArray = insertionSort([4, 3, 8, 1]); // [1, 3, 4, 8]
// Custom comparator
// descending
let sortedArray = insertionSort([4, 3, 8, 1], (a, b) => b - a); // [8, 4, 3, 1]
// ascending (string length)
let sortedArray = insertionSort(["111", "1", "11"], (a, b) => a.length - b.length); // ["1", "11", "111"]
// descending (string length)
let sortedArray = insertionSort(["111", "1", "11"], (a, b) => b.length - a.length); // ["111", "11", "1"]
import { mergeSort } from "@clarketm/super";
// General usage
// ascending
let sortedArray = mergeSort([4, 3, 8, 1]); // [1, 3, 4, 8]
// Custom comparator
// descending
let sortedArray = mergeSort([4, 3, 8, 1], (a, b) => b - a); // [8, 4, 3, 1]
// ascending (string length)
let sortedArray = mergeSort(["111", "1", "11"], (a, b) => a.length - b.length); // ["1", "11", "111"]
// descending (string length)
let sortedArray = mergeSort(["111", "1", "11"], (a, b) => b.length - a.length); // ["111", "11", "1"]
import { quickSort } from "@clarketm/super";
// General usage
// ascending
let sortedArray = quickSort([4, 3, 8, 1]); // [1, 3, 4, 8]
// Custom comparator
// descending
let sortedArray = quickSort([4, 3, 8, 1], (a, b) => b - a); // [8, 4, 3, 1]
// ascending (string length)
let sortedArray = quickSort(["111", "1", "11"], (a, b) => a.length - b.length); // ["1", "11", "111"]
// descending (string length)
let sortedArray = quickSort(["111", "1", "11"], (a, b) => b.length - a.length); // ["111", "11", "1"]
import { selectionSort } from "@clarketm/super";
// General usage
// ascending
let sortedArray = selectionSort([4, 3, 8, 1]); // [1, 3, 4, 8]
// Custom comparator
// descending
let sortedArray = selectionSort([4, 3, 8, 1], (a, b) => b - a); // [8, 4, 3, 1]
// ascending (string length)
let sortedArray = selectionSort(["111", "1", "11"], (a, b) => a.length - b.length); // ["1", "11", "111"]
// descending (string length)
let sortedArray = selectionSort(["111", "1", "11"], (a, b) => b.length - a.length); // ["111", "11", "1"]
MIT © Travis Clarke