{"id":13632462,"url":"https://github.com/ignlg/heap-js","last_synced_at":"2025-05-15T04:04:28.589Z","repository":{"id":46775595,"uuid":"98323278","full_name":"ignlg/heap-js","owner":"ignlg","description":"Efficient Binary heap (priority queue, binary tree) data structure for JavaScript / TypeScript. Includes JavaScript methods, Python's heapq module methods, and Java's PriorityQueue methods.","archived":false,"fork":false,"pushed_at":"2024-12-28T15:50:19.000Z","size":2476,"stargazers_count":147,"open_issues_count":7,"forks_count":11,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-10T11:07:16.521Z","etag":null,"topics":["array-heap","binary-heap","binary-trees","data-structures","heap","javascript","nodejs","priority-queue","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ignlg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["ignlg"]}},"created_at":"2017-07-25T15:43:08.000Z","updated_at":"2025-05-05T15:16:17.000Z","dependencies_parsed_at":"2024-01-15T09:10:14.973Z","dependency_job_id":"98ed115c-36d2-4847-a8a3-6516b9c8978e","html_url":"https://github.com/ignlg/heap-js","commit_stats":{"total_commits":201,"total_committers":3,"mean_commits":67.0,"dds":0.07462686567164178,"last_synced_commit":"a3bb403b4e127406122fef2ff688ee762f8d987a"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignlg%2Fheap-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignlg%2Fheap-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignlg%2Fheap-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignlg%2Fheap-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ignlg","download_url":"https://codeload.github.com/ignlg/heap-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270641,"owners_count":22042858,"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":["array-heap","binary-heap","binary-trees","data-structures","heap","javascript","nodejs","priority-queue","typescript"],"created_at":"2024-08-01T22:03:03.797Z","updated_at":"2025-05-15T04:04:28.539Z","avatar_url":"https://github.com/ignlg.png","language":"TypeScript","funding_links":["https://github.com/sponsors/ignlg"],"categories":["TypeScript"],"sub_categories":[],"readme":"# ![Heap.js](assets/heap-js.png) Heap.js\n\n[![npm version](https://img.shields.io/npm/v/heap-js.svg?style=flat)](https://www.npmjs.com/package/heap-js)\n[![Coverage Status](https://img.shields.io/coveralls/ignlg/heap-js/master.svg?style=flat)](https://coveralls.io/github/ignlg/heap-js?branch=master)\n\n**Efficient Binary heap (priority queue, binary tree) data structure for JavaScript / TypeScript.**\n\n**Now with support for async comparators with the new `HeapAsync` class!**\n\nIncludes JavaScript methods, Python's _heapq module_ methods, and Java's _PriorityQueue_ methods.\n\nEasy to use, known interfaces, tested, and well-documented JavaScript binary heap library.\n\nInstances are `integer min heap` by default.\n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ignlg/heap-js)\n\n## Is it faster than sorting an array?\n\nIt depends on your usage, but for some scenarios, it is much faster:\n\n```\nheap vs array: push + pop/unshift 50\n heap  x 72,130 ops/sec ±0.50% (93 runs sampled)\n array x 121 ops/sec ±78.09% (5 runs sampled)\n\nheap vs array: push + peek 20\n heap  x 622,332 ops/sec ±27.93% (63 runs sampled)\n array x 207 ops/sec ±78.18% (5 runs sampled)\n\nheap vs array: push + top(1) of 100\n heap  x 124,835 ops/sec ±40.37% (61 runs sampled)\n array x 123 ops/sec ±78.49% (5 runs sampled)\n\nheap vs array: push + top(50) of 100\n heap  x 59,210 ops/sec ±17.66% (82 runs sampled)\n array x 125 ops/sec ±78.79% (5 runs sampled)\n```\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=ignlg/heap-js\u0026type=Date)](https://star-history.com/#ignlg/heap-js\u0026Date)\n\n## Changelog\n\n### 2.6\n\n- Improves performance of remove and sorting methods.\n- Improves tests and documentation.\n\n### 2.5\n\n- Improves the `limit` property to support negative, Infinity, and NaN values. They will be set as `0` and the heap will not be limited.\n- Adds the `setLimit` method to set the limit of the heap. It returns `NaN` if the limit is negative, or NaN. This method is useful to check if the limit was set as expected.\n- Improves tests and documentation.\n\n### 2.4\n\n- Adds the `indexOf` method to find the first index of an element in the heap.\n- Adds the `indexOfEvery` method to find all indexes of an element in the heap.\n- Changes the `remove` method to use the `indexOf` method.\n- Changes the `contains` method to use the `indexOf` method.\n- Improves documentation.\n\n### 2.3\n\n- Adds the `HeapAsync` class, with async methods and supporting async comparators. It is a drop-in replacement for the `Heap` class with Promises.\n\n### 2.2\n\n- Fixes `.iterator()` method to follow [Java's PriorityQueue implementation:\n  ](https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html)\n  \u003e The Iterator provided in method [iterator()](\u003chttps://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html#iterator()\u003e) is not guaranteed to traverse the elements of the priority queue in any particular order.\n\nNotice that _using the heap directly as an iterator will consume the heap,_ as Python's `heapq` implementation does.\n\n### 2.1\n\n- Adds `Heap.nlargest` as in `heapq`.\n- Adds `Heap.nsmallest` as in `heapq`.\n- Sanitizes `top` / `bottom` input to force an integer.\n- Linted with Eslint.\n\n### 2.0\n\nThe main breaking change is that now _`top(N)` does NOT sort the output_, because sorting should not be part of the spec for a priority queue. The output is the top N elements, and they will be _partially ordered_ with the peek at index `0` by definition.\n\n- `top(N)` is unordered, only the first element is guaranteed to be the top priority element.\n- Fixes custom heap issue [#31](https://github.com/ignlg/heap-js/issues/31).\n- Performance improvements.\n- More tests, including those for custom heaps.\n- Auxiliary experimental `top(N)` algorithms.\n- (WIP) Benchmarks.\n\n### 1.5\n\n- Adds the `Iterator` interface and `iterator()` method.\n\n## Examples\n\n### Basic usage\n\n#### Min Heap\n\nA heap where the smallest element is always at the top. It is the default heap.\n\n```js\nimport { Heap } from 'heap-js';\n\n// Min Heap by default\nconst minHeap = new Heap();\n\n// Initialize the heap with an array\nminHeap.init([5, 18, 1]);\n// Push a new value\nminHeap.push(2);\n\nconsole.log(minHeap.peek()); //\u003e 1\nconsole.log(minHeap.pop()); //\u003e 1\nconsole.log(minHeap.peek()); //\u003e 2\n```\n\n#### Max Heap\n\nA heap where the largest element is always at the top.\n\n```js\nimport { Heap } from 'heap-js';\n\n// Max Heap\nconst maxHeap = new Heap(Heap.maxComparator);\n\n// Initialize the heap with an array\nmaxHeap.init([3, 4, 1, 12, 8]);\n// Push a new value\nmaxHeap.push(2);\n\nconsole.log(maxHeap.peek()); //\u003e 12\nconsole.log(maxHeap.pop()); //\u003e 12\nconsole.log(maxHeap.peek()); //\u003e 8\n```\n\n#### Custom Heap\n\nA heap where the most important element is always at the top, but the elements are objects with a `priority` property.\n\n```js\nimport { Heap } from 'heap-js';\n\nconst customPriorityComparator = (a, b) =\u003e a.priority - b.priority;\n// Custom Heap\nconst customHeap = new Heap(customPriorityComparator);\n\n// Initialize the heap with an array\ncustomHeap.init([{ priority: 5 }, { priority: 18 }, { priority: 1 }]);\n// Push a new value\ncustomHeap.push({ priority: 2 });\n\nconsole.log(customHeap.peek()); //\u003e { priority: 1 }\nconsole.log(customHeap.pop()); //\u003e { priority: 1 }\nconsole.log(customHeap.peek()); //\u003e { priority: 2 }\n```\n\n#### Min HeapAsync\n\nA heap where the most important element is always at the top, the elements are objects with a `priority` property, and the comparator function is asynchronous. Implements the same interface as `Heap`, but almost all methods return a `Promise`.\n\n```js\nimport { HeapAsync } from 'heap-js';\n\nconst customPriorityComparator = (a, b) =\u003e Promise.resolve(a.priority - b.priority);\n// Custom HeapAsync\nconst customHeap = new HeapAsync(customPriorityComparator);\n\n// Initialize the heap with an array\nawait customHeap.init([{ priority: 5 }, { priority: 18 }, { priority: 1 }]);\n// Push a new value\nawait customHeap.push({ priority: 2 });\n\nconsole.log(customHeap.peek()); //\u003e { priority: 1 }\nconsole.log(await customHeap.pop()); //\u003e { priority: 1 }\nconsole.log(await customHeap.peek()); //\u003e { priority: 2 }\n```\n\n### Priority Queue usage\n\n#### JavaScript / Python-style iterator (recommended)\n\nIterates over the heap consuming it, and guarantees to traverse the elements of the heap in the order of priority. Useful.\n\n```js\nconst { Heap } = require('heap-js');\n\n// Get all tasks from the database\nconst tasks = db.collection.find().toArray();\n// The most important task has the lowest priority value\nconst customPriorityComparator = (a, b) =\u003e a.priority - b.priority;\n\n// Create the priority queue\nconst priorityQueue = new Heap(customPriorityComparator);\n// Initialize the priority queue with the tasks\npriorityQueue.init(tasks);\n\n// Iterator that will consume the heap while traversing it in the order of priority\nfor (const task of priorityQueue) {\n  console.log(task);\n}\n```\n\n#### Java-style iterator (not recommended)\n\nIterates over the heap without consuming it, but does not guarantee to traverse the elements of the heap in any particular order. Barely useful.\n\n```js\nconst { Heap } = require('heap-js');\n\n// Get all tasks from the database\nconst tasks = db.collection.find().toArray();\n// The most important task has the lowest priority value\nconst customPriorityComparator = (a, b) =\u003e a.priority - b.priority;\n\nconst priorityQueue = new Heap(customPriorityComparator);\n// Initialize the priority queue with the tasks\npriorityQueue.init(tasks);\n\n// Iterator, the Java way, that will not consume the heap BUT does not guarantee to traverse the elements of the heap in any particular order. Barely useful.\nfor (const task of priorityQueue.iterator()) {\n  console.log(task);\n}\n```\n\n### Python-like static methods\n\n```js\nimport { Heap } from 'heap-js';\nconst numbers = [2, 3, 7, 5];\n\n// Changes the array elements order into a heap in-place\nHeap.heapify(numbers);\nconsole.log(numbers); //\u003e [ 2, 3, 5, 7 ]\n\n// Pushes a new value to the heap\nHeap.heappush(numbers, 1);\nconsole.log(numbers); //\u003e [ 1, 2, 5, 7, 3 ]\n```\n\n## Installation\n\n```bash\nyarn add heap-js # if you use yarn\n\nnpm install --save heap-js # if you use npm\n```\n\n## Constructor\n\n### Heap\n\n```js\nnew Heap([comparator]);\n```\n\n### HeapAsync\n\n```js\nnew HeapAsync([asyncComparator]);\n```\n\n## Comparators already included\n\n- `Heap.minComparator`: Uses less-than operator to compare elements. It is the default comparator.\n- `Heap.maxComparator`: Uses greater-than operator to compare elements.\n- `Heap.minComparatorNumber`: Uses subtraction `a - b` to compare elements.\n- `Heap.maxComparatorNumber`: Uses subtraction `b - a` to compare elements.\n\n## Implements JavaScript-style methods\n\n- `for (const value of heap)` directly usable as an Iterator, **consumes the heap.**\n- `length` of the heap.\n- `limit` the number of elements in the heap.\n- `pop()` the top element.\n- `push(...elements)` one or more elements to the heap.\n- `pushpop(element)` faster than `push` \u0026 `pop`.\n- `replace(element)` faster than `pop` \u0026 `push`.\n- `top(number?)` most valuable elements from the heap.\n- `bottom(number?)` least valuable elements from the heap.\n- `indexOf(element, fn?)` returns the internal index of the first occurrence of the element in the heap.\n- `indexOfEvery(element, fn?)` returns an array with the internal indexes of all occurrences of the element in the heap.\n\n## Implements Java's `PriorityQueue` interface\n\n- `add(element)` to the heap.\n- `addAll([element, element, ... ])` to the heap, faster than loop `add`.\n- `clear()`\n- `clone()`\n- `comparator()`\n- `contains(element, fn?)`\n- _`element()` alias of `peek()`_\n- `isEmpty()`\n- `iterator()` returns the same as `toArray()` because it is iterable and follows Java's implementation. Barely useful. Use `for (const value of heap)` instead.\n- _`offer(element)` alias of `add(element)`_\n- `peek()`\n- _`poll()` alias of `pop()`_\n- `remove(element?)`\n- _`removeAll()` alias of `clear()`_\n- _`size()` alias of `length`_\n- `toArray()`\n- `toString()`\n\nTo do:\n\n- `containsAll`\n- `equals`\n- `retainAll`\n\n## Implements static Python's `heapq` interface\n\n- `Heap.heapify(array, comparator?)` that converts an array to an array-heap.\n- `Heap.heappop(heapArray, comparator?)` that takes the peek of the array-heap.\n- `Heap.heappush(heapArray, item, comparator?)` that appends elements to the array-heap.\n- `Heap.heappushpop(heapArray, item, comparator?)` faster than `heappush` \u0026 `heappop`.\n- `Heap.heapreplace(heapArray, item, comparator?)` faster than `heappop` \u0026 `heappush`.\n- `Heap.nlargest(n, iterable, comparator?)` that gets the `n` most valuable elements of an iterable.\n- `Heap.nsmallest(n, iterable, comparator?)` that gets the `n` least valuable elements of an iterable.\n\nExtras:\n\n- `Heap.heaptop(n, heapArray, comparator?)` that returns the `n` most valuable elements of the array-heap\n- `Heap.heapbottom(n, heapArray, comparator?)` that returns the `n` least valuable elements of the array-heap\n\nTo do:\n\n- `merge(...iterables, comparator?)`\n\n## Documentation\n\n\u003chttps://ignlg.github.io/heap-js/\u003e\n\n## Sponsor\n\nWe are looking for sponsors to help us maintain and improve **Heap.js**. If you're interested in supporting this project, please get in touch with us.\n\n## Collaborate\n\nWould you like to contribute to **Heap.js**? Feel free to submit a pull request, open an issue, or reach out to the maintainers. We welcome your feedback and ideas!\n\n### Dev setup\n\n```bash\nyarn\n```\n\n### Tests\n\n```bash\nnpm run test\n```\n\n### Benchmarks\n\n```bash\nnpm run benchmarks\n```\n\n### License\n\nHeap.js is [BSD 3-Clause Licensed](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fignlg%2Fheap-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fignlg%2Fheap-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fignlg%2Fheap-js/lists"}