{"id":19138021,"url":"https://github.com/lemonpi/bbst","last_synced_at":"2025-05-06T20:44:28.090Z","repository":{"id":73435233,"uuid":"78319834","full_name":"LemonPi/bbst","owner":"LemonPi","description":"Balanced binary search trees in ES6 Javascript with fast iteration","archived":false,"fork":false,"pushed_at":"2017-01-10T09:52:58.000Z","size":21,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-19T14:57:57.247Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LemonPi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-08T03:49:53.000Z","updated_at":"2023-09-22T06:16:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"d1aabeae-9a94-4fb4-b3d0-672157f8059c","html_url":"https://github.com/LemonPi/bbst","commit_stats":{"total_commits":18,"total_committers":2,"mean_commits":9.0,"dds":"0.11111111111111116","last_synced_commit":"f1c0f6981765b43fd15af9a5e1a0c6fc955ea6a1"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LemonPi%2Fbbst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LemonPi%2Fbbst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LemonPi%2Fbbst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LemonPi%2Fbbst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LemonPi","download_url":"https://codeload.github.com/LemonPi/bbst/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252769077,"owners_count":21801373,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T06:41:28.410Z","updated_at":"2025-05-06T20:44:28.031Z","avatar_url":"https://github.com/LemonPi.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Balanced binary search trees in ES6 Javascript for Node.js and browsers\nThe underlying implementation is a [Treap](https://en.wikipedia.org/wiki/Treap), which provides balance with high probability. \nThis implementation focuses on fast iteration, and provides generators for doing so.\n\nTreaps are simple and fast. In most cases, it provides up to 4x faster inserts, and 2x faster erases than a similar RB tree implementation.\n\nDeterministic behaviour can be achieved by seeding the RNG.\n\n## Installation\nPackage name is `bbst`\n\n```bash\nnpm install bbst --save\n```\n\n## Test\n```bash\nnpm install mocha\n\n// perform random test\nnpm test\n\n// test with specific seed \"seed\"\nnpm test seed\n```\n\n## Usage\nThe API provides `insert`, `changeKey`, `find`, `erase`, iteration, `reverseIterator`, `size`, `height`, `print`, and variants of the above (to be covered in examples below).\n\nFirst you need to include the module, which is easy in both node and a browser (look at index.html).\n\n### node\n```javascript\nconst BST = require(\"bbst\");\n```\n\n### browser\n```html\n\u003chtml\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cscript src=\"src/treap.js\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003cscript\u003e\nconst BST = Treap;\n\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\nFrom this point on, usage is the same on both platforms; let's assume we name the class `BST`.\n\n### deterministic seed\n```javascript\nBST.seedrandom(\"some value\");\n```\n\n### construction\n```javascript\nconst bst = new BST();\n```\n\n### insert\nInsert takes 1 object that is required to have a `key` property that can be compared. An `Error` will be thrown if something is inserted without a `key`. The inserted object can have any other property.\n```javascript\nbst.insert({key:1, name:\"Buzz Lightyear\"});\n```\n\nDuplicate keys are not guarenteed to remain in insertion order.\n```javascript\nbst.insert({key:1, name:\"An imposter\"});\n// bst.find(1) will find them in a random order\n```\n\n### iteration\nIterating forward will do so in increasing key order\n```javascript\nfor (let node of bst) {\n  console.log(node.key);  // print keys smallest to largest\n}\nfor (let node of bst.reverseIterator()) {\n  console.log(node.key);  // print keys largest to smallest\n}\n```\nThis is very useful for game tree searches as you iterate through possible moves in place rather than creating and sorting them at each step. This is especially powerful combined with `changeKey`. For each step, instead of creating a new state, simply change the current one to the next one while tracking the changes. If you have n possible moves, at each step you use `O(1)` memory instead of `O(n)`. \n\nI use this in a minimax algorithm with alpha-beta pruning so that the best moves are explored first, which often causes most of the other moves to be pruned and thus not generated.\n\n### changeKey\nA small change to a key's value can be dealt with faster than deleting and reinserting the node with `changeKey`.\n```javascript\nconst bst = new BST();\nfor (let key = 0; key \u003c 1000000; ++key) {\n  bst.insert({key});\n}\nconst node = bst.find(4000);\n// takes many fewer operations since it searches from node up\nbst.changeKey(node, 4001);\n```\n\n### print\nThe tree comes with pretty printing that works in consoles and browsers, as well as returning the string.\n```javascript\nconst bst = new BST();\nfor (let key = 0; key \u003c 10; ++key) {\n    bst.insert({key});\n}\nbst.print();\n```\nResults in something similar to\n```\n4\n├ 1\n│ ├ 0\n│ └ 2\n│   ├ \n│   └ 3\n└ 9\n  └ 7\n    ├ 5\n    │ ├ \n    │ └ 6\n    └ 8\n```\n\nprint accepts a custom printer function for printing more than just the node key.\n```javascript\nbst.print((node)=\u003e {\n  // return something printable, such as a string\n  return node.key + \":\" + node.name;\n});\n```\n\n\n\n### find\nAll failed finds will return `BST.NIL`. The basic find retrieves the top-most node with matching key. \n```javascript\nconst node = bst.find(5);\nconst nonNode = bst.find(11);\nassert(nonNode === BST.NIL);  // true\n```\nIf there is temporal locality (you need it soon after you found it, but not immediately after), then `findAndElevate` will make subsequent finds faster.\n```javascript\nconst hotNode = bst.find(5);\n```\nIf your data has duplicate keys and you care about finding all of them or a specific one, then use `findFirst` and `findNext`.\n`findFirst` takes the key to find, `findNext` takes the previous node (and is `O(1)` time).\n```javascript\nbst.insert({key:5, fruit:\"Pomelo\"});\nbst.insert({key:5, fruit:\"Tomato\"});\nlet found = bst.findFirst(5);\nwhile (found !== BST.NIL) {\n  console.log(found.fruit);\n  found = bst.findNext(found);\n}\n```\n\n### erase\nErase the top-most node with a matching key, or do nothing if it doesn't exist\n```javascript\nbst.erase(5);\n```\nErase a specific node, which is useful for duplicates and faster if you already found the node\n```javascript\nbst.erase(bst.find(5));\n```\n\n### size\nGet number of nodes\n```javascript\nlet bst = new BST();\nbst.size(); // 0\n\nfor (let key = 0; key \u003c 10; ++key) {\n  bst.insert({key});\n}\nbst.size(); // 10\n```\n\n### height\nMaximum pointer distance to root node. It is expected to be `O(lg(bst.size()))`, and is more likely with larger size.\n```javascript\nlet bst = new BST();\nbst.height(); // 0\n\n\nfor (let key = 0; key \u003c 1000; ++key) {\n  bst.insert({key});\n}\nbst.height(); // about lg(bst.size())\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemonpi%2Fbbst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flemonpi%2Fbbst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemonpi%2Fbbst/lists"}