UNPKG

esds

Version:

ES6 JS lightweight data structures (Priority Queue, Binary Search Tree (BST), Graph, Bloom Filters, Trie, Queue, Stack, Linked-List)

552 lines (450 loc) β€’ 17.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Home</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Home</h1> <h3> </h3> <section> <article><p><a href="https://github.com/jayalbo/ESDS/graphs/contributors"><img src="https://img.shields.io/github/contributors/jayalbo/ESDS.svg?style=for-the-badge" alt="Contributors"></a> <a href="https://www.npmjs.com/package/esds"><img src="https://img.shields.io/npm/dw/esds?style=for-the-badge" alt="Downloads"></a> <a href="https://github.com/jayalbo/ESDS/network/members"><img src="https://img.shields.io/github/forks/jayalbo/ESDS.svg?style=for-the-badge" alt="Forks"></a> <a href="https://github.com/jayalbo/ESDS/stargazers"><img src="https://img.shields.io/github/stars/jayalbo/ESDS.svg?style=for-the-badge" alt="Stargazers"></a> <a href="https://github.com/jayalbo/ESDS/issues"><img src="https://img.shields.io/github/issues/jayalbo/ESDS.svg?style=for-the-badge" alt="Issues"></a> <a href="https://github.com/jayalbo/ESDS/blob/master/LICENSE.txt"><img src="https://img.shields.io/github/license/jayalbo/ESDS.svg?style=for-the-badge" alt="MIT License"></a></p> <!-- PROJECT LOGO --> <br /> <p align="center"> <h3 align="center">ESDS</h3> <p align="center"> ES Javascript Data Structures (Priority Queue, Binary Search Tree (BST), Graph, Trie, Bloom Filter, Queue, Stack, Linked List) <br /> <a href="https://jayalbo.github.io/ESDS/"><strong>Explore the docs Β»</strong></a> <br /> <br /> <a href="https://github.com/jayalbo/ESDS/issues">Report Bug 🐞</a> Β· <a href="https://github.com/jayalbo/ESDS/discussions">Request Feature πŸ—³</a> </p> </p> <!-- TABLE OF CONTENTS --> <details open="open"> <summary>Table of Contents</summary> <ol> <li> <a href="#getting-started">Getting Started 🚦 </a> <ul> <li><a href="#installation">Installation πŸ’Ύ</a></li> </ul> </li> <li><a href="#examples">Usage πŸ“š</a> <ul> <li><a href="#examples">Examples πŸ“‘</a> <ul> <li><a href="#priority-queue">Priority Queue πŸ“š</a></li> <li><a href="#binary-search-tree">Binary Search Tree (BST) πŸŽ„</a></li> <li><a href="#graph">Graph ፨</a> <ul> <li><a href="#undirected">Undirected ↔</a></li> <li><a href="#directed">Directed β†’</a></li> </ul> </li> <li><a href="#trie">Trie 🌲</a></li> <li><a href="#bloom-filter">Bloom Filter ⚘</a></li> <li><a href="#queue-stack">Queue πŸ“š / Stack πŸ₯ž</a></li> <li><a href="#linked-list">Linked ListπŸ“</a></li> </ul> </li> </ul> </li> <li><a href="#roadmap">Roadmap πŸ“</a></li> <li><a href="#contributing">Contributing πŸ’ͺ</a></li> <li><a href="#license">License πŸ“</a></li> <li><a href="#contact">Contact πŸ“§</a></li> </ol> </details> <!-- GETTING STARTED --> <h2>Getting Started</h2> <p>To get a local copy up and running follow these simple steps.</p> <h3>Installation</h3> <ol> <li>Install NPM package<pre class="prettyprint source lang-sh"><code>npm i esds </code></pre> </li> </ol> <!-- USAGE EXAMPLES --> <h2>Examples</h2> <h3>Priority Queue</h3> <pre class="prettyprint source lang-javascript"><code>import { PriorityQueue } from &quot;esds&quot;; const minPQ = new PriorityQueue(&quot;min&quot;); // min PQ (default if not provided) const maxPQ = new PriorityQueue(&quot;max&quot;); // max PQ const arr = [20, 40, 30, 50, 15, 10, 5]; arr.forEach((element) => { minPQ.add(element); maxPQ.add(element); }); console.log(minPQ.peek); // 5 console.log(maxPQ.peek); // 50 while (!minPQ.isEmpty) { console.log(minPQ.poll()); } /* 5 10 15 20 30 40 50 */ while (!maxPQ.isEmpty) { console.log(maxPQ.poll()); } /* 50 40 30 20 15 10 5 */ // Custom comparator const comparator = (a, b) => a.age - b.age; // Using age (min) const customPQ = new PriorityQueue(&quot;custom&quot;, comparator); const Person = function (name, age, role) { this.name = name; this.age = age; this.role = role; }; customPQ.add(new Person(&quot;Jane Doe&quot;, 26, &quot;Software Engineer&quot;)); customPQ.add(new Person(&quot;John Doe&quot;, 28, &quot;Cloud Engineer&quot;)); customPQ.add(new Person(&quot;Ordinary Joe&quot;, 42, &quot;QA&quot;)); customPQ.add(new Person(&quot;Janie Doe&quot;, 20, &quot;Support Engineer&quot;)); customPQ.add(new Person(&quot;Fred Bloggs&quot;, 19, &quot;Intern&quot;)); // Contains function using object console.log(customPQ.contains(new Person(&quot;Janie Doe&quot;, 20, &quot;Support Engineer&quot;))); // true // Poll while (!customPQ.isEmpty) { console.log(customPQ.poll()); } /* { name: 'Fred Bloggs', age: 19, role: 'Intern' } { name: 'Janie Doe', age: 20, role: 'Support Engineer' } { name: 'Jane Doe', age: 26, role: 'Software Engineer' } { name: 'John Doe', age: 28, role: 'Cloud Engineer' } { name: 'Ordinary Joe', age: 42, role: 'QA' } */ </code></pre> <h3>Binary Search Tree</h3> <pre class="prettyprint source lang-Javascript"><code>import { BST, List} from &quot;esds&quot;; const bst = new BST(); // Add Elements bst.add(10, &quot;Ten&quot;); bst.add(1, &quot;One&quot;); bst.add(5, &quot;Five&quot;); bst.add(7, &quot;Seven&quot;); bst.add(2, &quot;Two&quot;); bst.add(0, &quot;Zero&quot;); bst.add(8, &quot;Eight&quot;); console.log(bst.toArray(&quot;in-order&quot;)); // [ 0, 1, 2, 5, 7, 8, 10 ] console.log(bst.toArray(&quot;pre-order&quot;)); // [ 10, 1, 0, 5, 2, 7, 8 ] console.log(bst.toArray(&quot;post-order&quot;)); // [ 0, 2, 8, 7, 5, 1, 10 ] console.log(bst.toArray(&quot;reverse-in-order&quot;)); // [ 10, 8, 7, 5, 2, 1, 0 ] // Get Element console.log(bst.get(7)); /* TreeElement { key: 7, value: 'Seven', left: null, right: TreeElement { key: 8, value: 'Eight', left: null, right: null } } */ // Update Element bst.update(8, &quot;はけ&quot;); console.log(bst.get(8).value); // はけ // Has console.log(bst.has(5)); // true // Remove Element bst.remove(5); console.log(bst.has(5)); // false // Handling duplicates (Using Linked-list) if (bst.has(7)) { // true const list = new List(); list.add(bst.get(7).value); // Added &quot;Seven&quot; list.add([&quot;Siete&quot;, &quot;しけ&quot;, &quot;δΈƒ&quot;, &quot;Sieben&quot;]); bst.update(7, list); } console.log(bst.get(7).value.toArray()); // [ 'Seven', 'Siete', 'しけ', 'δΈƒ', 'Sieben' ] // Remove Elements using an iterator in order to prevent a significant unbalanced BST // JS Generator function function* iterator(arr) { let i = 0; while (true) { yield arr[i++]; if (i === arr.length) i = 0; } } const removeType = iterator([&quot;predecessor&quot;, &quot;successor&quot;]); // in-order predecessor, and in-order successor [10, 1, 0, 5, 7].forEach((value) => bst.remove(value, removeType.next().value)); console.log(bst.toArray()); // Default: in-order // [ 2, 8 ] </code></pre> <h3>Graph</h3> <h4>Undirected</h4> <pre class="prettyprint source lang-Javascript"><code>import { Graph } from &quot;esds&quot;; const graph = new Graph(); // Creates a new undirected graph // Add nodes (Users) graph.addNode(1, &quot;Randall&quot;); graph.addNode(2, &quot;Mellisa&quot;); graph.addNode(3, &quot;Cecelia&quot;); graph.addNode(4, &quot;Velda&quot;); graph.addNode(5, &quot;Rossie&quot;); //Add Edges (Friendships) graph.addEdge(1, 2); // Randall - Mellisa graph.addEdge(2, 5); // Mellisa - Rossie graph.addEdge(3, 4); // Cecelia - Velda graph.addEdge(4, 1); // Velda - Randall graph.addEdge(5, 1); // Rossie - Randall // Check if connection exists (Users are friends) console.log(graph.nodesConnected(2, 3)); // Mellisa & Cecelia: Output: false console.log(graph.nodesConnected(1, 5)); // Randall & Rossie: Output: true // Check distance between two nodes (Users) console.log(graph.getWeight(2, 3)); // Mellisa & Cecelia: Output: 3rd level friends console.log(graph.getWeight(1, 5)); // Randall & Rossie: Output: 1st level friends (Users are friends) // Get Path between nodes (Friendship relation between two users) console.log(graph.getPath(2, 3).map((value) => graph.getNode(value.node))); // [ 'Mellisa', 'Randall', 'Velda', 'Cecelia' ] console.log(graph.getPath(1, 5).map((value) => graph.getNode(value.node))); // [ 'Randall', 'Rossie' ] </code></pre> <h4>Directed</h4> <pre class="prettyprint source lang-Javascript"><code>import { Graph } from &quot;esds&quot;; const graph = new Graph(true); // Creates a new directed graph // Add Nodes (Cities) graph.addNode(1, &quot;City Ξ‘&quot;); graph.addNode(2, &quot;City Ξ²&quot;); graph.addNode(3, &quot;City Ξ“&quot;); graph.addNode(4, &quot;City Ξ”&quot;); graph.addNode(5, &quot;City Ξ΅&quot;); // Add Edges (Routes between cities (one-way)) graph.addEdge(1, 3, 75); // Alpha (Ξ‘) -> Gamma (Ξ“), distance 75 miles graph.addEdge(2, 5, 325); // Beta (Ξ²) -> Epsilon (Ξ΅), distance 325 miles graph.addEdge(3, 1, 125); // Gamma (Ξ“) -> Alpha (Ξ±), distance 125 miles graph.addEdge(4, 2, 100); // Delta (Ξ”) -> Beta (Ξ²), distance 100 miles graph.addEdge(5, 1, 415); // Epsilon (Ξ΅) -> Alpha (Ξ‘), distance 415 miles graph.addEdge(5, 3, 550); // Epsilon (Ξ΅) -> Gamma (Ξ“), distance 550 miles // Check if connection exists (Route between cities exists) console.log(graph.nodesConnected(2, 3)); // Beta & Gamma: Output: false console.log(graph.nodesConnected(5, 1)); // Epsilon & Alpha: Output: true // Get Path between nodes (Route between two cities) by lowest number of intermediate nodes let routeADistance = 0; const routeA = graph.getPath(2, 3).map((value) => { // Between Beta (Ξ²) & Gamma (Ξ“) routeADistance += value.weight; return graph.getNode(value.node); }); console.log(routeA, routeADistance); /* ([Route] Total distance in miles) [ 'City Ξ²', 'City Ξ΅', 'City Ξ“' ] 875 */ // Get Path between nodes (Route between two cities) by lowest distance (Dijkstra algorithm) let routeB = graph.getPathWeighted(2, 3); // Between Beta (Ξ²) & Gamma (Ξ“) let routeBDistance = routeB.distance; routeB = routeB.nodes.map((value) => graph.getNode(value)); console.log(routeB, routeBDistance); /* ([Route] Total distance in miles) [ 'City Ξ²', 'City Ξ΅', 'City Ξ‘', 'City Ξ“' ] 815 */ </code></pre> <h4>Use cases: Social graphs, recommendation engines, navigation, supply chain, etc.</h4> <h4>Flight Routes Example: https://bit.ly/3ApNrDA</h4> <p><img src="https://i.imgur.com/XZdmzAW.jpg" alt="Flight Routes"></p> <h3>Trie</h3> <pre class="prettyprint source lang-Javascript"><code>import { Trie } from &quot;esds&quot;; const countries = [ &quot;United States of America&quot;, &quot;Canada&quot;, &quot;Argentina&quot;, &quot;Japan&quot;, &quot;Italy&quot;, &quot;Germany&quot;, &quot;Brazil&quot;, &quot;Armenia&quot;, &quot;Aruba&quot;, ]; const trie = new Trie(); countries.forEach((element) => trie.add(element)); // Add countries to the Trie // Check if element exists console.log(trie.contains(&quot;Argentina&quot;)); // True console.log(trie.contains(&quot;Spain&quot;)); // False // Update content trie.update(&quot;Argentina&quot;, &quot;πŸ‡¦πŸ‡·&quot;); trie.update(&quot;United States of America&quot;, &quot;πŸ‡ΊπŸ‡Έ&quot;); // Get content console.log(trie.get(&quot;Argentina&quot;)); // πŸ‡¦πŸ‡· console.log(trie.get(&quot;United States of America&quot;)); // πŸ‡ΊπŸ‡Έ // Retrieve Sub-Trie (DFS) const prefix = &quot;Ar&quot;; const result = trie.find(prefix); const dfs = (word, node) => { if (node.child?.size > 0) { node.child.forEach((value) => { dfs(`${word}${value.key}`, value); }); } if (node.end) console.log(`${word}`); /* Argentina Armenia Aruba */ }; dfs(prefix, result); // toArray() console.log(trie.toArray()); /* ['United States of America','Canada', 'Argentina', 'Armenia', 'Aruba', 'Japan', 'Italy', 'Germany','Brazil'] */ </code></pre> <h4>Use cases: Auto-complete, string search, word suggestion, prefix, IP routing, etc.</h4> <h4>Word Prediction Example: https://bit.ly/37hYhPL</h4> <p><img src="https://i.imgur.com/RVvFlyk.gif" alt="Word Prediction"></p> <h3>Bloom Filter</h3> <h4>A Bloom filter is a space-efficient probabilistic data structure that is used to test whether an element is a member of a set. More Info: https://bit.ly/3D9RmH8</h4> <pre class="prettyprint source lang-Javascript"><code>import { BloomFilter } from &quot;esds&quot;; // Create BF const BF = new BloomFilter(); // Add individual users BF.add(&quot;john_89@email.com&quot;); BF.add(&quot;jane2020@email.com&quot;); BF.add(&quot;Joe@email.com&quot;); BF.add(&quot;Doe.Jane@email.com&quot;); BF.add(&quot;Jim.1990@email.com&quot;); // Check individual users console.log(BF.has(&quot;Doe.Jane@email.com&quot;)); // True (User may exists) console.log(BF.has(&quot;Jimmy@email.com&quot;)); // False // Create second BF const BF2 = new BloomFilter(2048, 4); // Size 2048, Num. Hash rounds 4 const users = [ &quot;almost&quot;, &quot;dopey&quot;, &quot;eritrean&quot;, &quot;struggle&quot;, &quot;hospitable&quot;, &quot;factor&quot;, &quot;quail&quot;, ]; // Add multiple users BF2.add(users); // Check individual users console.log(BF2.has(&quot;struggle&quot;)); // True (User may exists) console.log(BF2.has(&quot;house&quot;)); // False // Check multiple values console.log( BF2.has([&quot;hospitable&quot;, &quot;monitor&quot;, &quot;dopey&quot;, &quot;factor&quot;, &quot;fan&quot;, &quot;quail&quot;]) ); // [ true, false, true, true, false, true ] </code></pre> <h4>Bloom Filters use cases:</h4> <ul> <li>Value lookup when false positives are acceptable</li> <li>Avoid expensive lookup operations against DB</li> <li>Content filtering</li> </ul> <h3>Queue-Stack</h3> <pre class="prettyprint source lang-JavaScript"><code>import {Queue, Stack} from 'esds'; const queue = new Queue(); const stack = new Stack(); queue.add([1,2,3]); queue.add(4); queue.add(5); stack.push([1,2]); stack.add(3); stack.add([4,5]); while (!queue.isEmpty){ console.log(queue.poll()); // 1, 2, 3, 4, 5 } while (!stack.isEmpty){ console.log(stack.pop()); // 5, 4, 3, 2, 1 } </code></pre> <h4>Linked List</h4> <pre class="prettyprint source lang-JavaScript"><code>import {List} from 'esds'; const a = new List(); a.add([1, 2, 3, 4]); console.log(a.toArray()); // [1, 2, 3, 4] a.add(5); a.add(&quot;Six&quot;); a.add({value: 7, str: &quot;Seven&quot;}); console.log(a.get(6).val); // &quot;Six&quot; let head = a.get(); while(head){ console.log(head.val); head = head.next; } /* 1 2 3 4 5 &quot;Six&quot; {value: 7, str: &quot;Seven&quot;} */ let b = a.subList(2, 5); console.log(b.toArray()); // [2, 3, 4, 5] </code></pre> <!-- ROADMAP --> <h2>Roadmap</h2> <p>See the <a href="https://github.com/jayalbo/ESDS/issues">open issues</a> for a list of proposed features (and known issues).</p> <!-- CONTRIBUTING --> <h2>Contributing</h2> <p>Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are <strong>greatly appreciated</strong>.</p> <ol> <li>Fork the Project</li> <li>Create your Feature Branch (<code>git checkout -b feature/AmazingFeature</code>)</li> <li>Commit your Changes (<code>git commit -m 'Add some AmazingFeature'</code>)</li> <li>Push to the Branch (<code>git push origin feature/AmazingFeature</code>)</li> <li>Open a Pull Request</li> </ol> <!-- LICENSE --> <h2>License</h2> <p>Distributed under the MIT License. See <code>LICENSE</code> for more information.</p> <!-- CONTACT --> <h2>Contact</h2> <p>Project Link: <a href="https://github.com/jayalbo/ESDS">https://github.com/jayalbo/ESDS</a></p> <!-- MARKDOWN LINKS & IMAGES --> <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --></article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="BloomFilter.html">BloomFilter</a></li><li><a href="BST.html">BST</a></li><li><a href="Element.html">Element</a></li><li><a href="Graph.html">Graph</a></li><li><a href="List.html">List</a></li><li><a href="Node.html">Node</a></li><li><a href="PriorityQueue.html">PriorityQueue</a></li><li><a href="Queue.html">Queue</a></li><li><a href="Stack.html">Stack</a></li><li><a href="TreeElement.html">TreeElement</a></li><li><a href="Trie.html">Trie</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.7</a> on Thu Sep 23 2021 00:49:18 GMT-0700 (Pacific Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>