js-data-structures
Data Structures (JavaScript)
Map vs Object, Set vs Array
- Prefer Map when keys are non-string (numbers, objects), when you add/remove entries often, when you need
.size - Prefer Object when keys are string/symbol, the shape is static and known at creation, or you need JSON serialization
- Prefer Set when uniqueness matters or you need fast
.has()lookups - Prefer Array when order and duplicates matter; when have fixed size array; need index access
Linked List
Single-linked list:
class LinkedList {
#head = null;
#length = 0;
push(data) {
this.#head = { data, next: this.#head };
this.#length++;
}
pop() {
if (!this.#head) return undefined;
const { data } = this.#head;
this.#head = this.#head.next;
this.#length--;
return data;
}
*[Symbol.iterator]() {
let node = this.#head;
while (node) {
yield node.data;
node = node.next;
}
}
}
Queue
Basic queue with array:
class Queue {
#buffer = [];
enqueue(item) {
this.#buffer.push(item);
}
dequeue() {
return this.#buffer.shift();
}
get length() {
return this.#buffer.length;
}
}
V8-optimized queue uses unrolled linked nodes with fixed-size buffers to avoid shift() O(n) cost:
class Node {
constructor(size) {
this.buffer = new Array(size);
this.readIdx = 0;
this.writeIdx = 0;
this.next = null;
}
enqueue(item) {
if (this.writeIdx >= this.buffer.length) return false;
this.buffer[this.writeIdx++] = item;
return true;
}
dequeue() {
if (this.readIdx >= this.writeIdx) return undefined;
return this.buffer[this.readIdx++];
}
}
Circular Buffer
class CircularBuffer {
#buffer;
#size;
#readIdx = 0;
#writeIdx = 0;
constructor(size) {
this.#size = size;
this.#buffer = new Array(size);
}
write(item) {
this.#buffer[this.#writeIdx] = item;
this.#writeIdx = (this.#writeIdx + 1) % this.#size;
}
read() {
const item = this.#buffer[this.#readIdx];
this.#readIdx = (this.#readIdx + 1) % this.#size;
return item;
}
}
Binary Search Tree
class BST {
constructor(data) {
this.data = data;
this.left = null;
this.right = null;
}
insert(data) {
if (data < this.data) {
if (this.left) this.left.insert(data);
else this.left = new BST(data);
} else {
if (this.right) this.right.insert(data);
else this.right = new BST(data);
}
}
}
More from metarhia/skills
javascript-code-style
Apply Metarhia JavaScript style. Use when writing or editing .js, .mjs, .ts files (with certain corrections for typescript), formatting code, or when the user asks about code style or linting.
5js-gof
Apply Gang of Four and related design patterns in JavaScript and TypeScript. Use when implementing creational, structural, or behavioral patterns, or when the user mentions factories, builder, prototype, flyweight, singleton, object pool, adapter, wrapper, decorator, proxy, bridge, composite, facade, chain of responsibility, command, interpreter, iterator, mediator, memento, EventEmitter, EventTarget, state, strategy, template method, visitor, revealing constructor, actor, service locator, or any other pattern.
2js-conventions
Apply Metarhia JavaScript style. Use when writing or editing .js, .mjs, .ts files (with certain corrections for typescript), formatting code, or when the user asks about code style or linting.
2npm-publish
Prepare an npm package for publishing. Handles version bump, CHANGELOG update, typings check, test run, README refresh, package.json audit, and npm pack verification. Use when the user asks to prepare a release, bump version, publish a package, or do release prep.
1error-handling
Apply error handling and recovery patterns in JavaScript/TypeScript or Node.js. Use when implementing error handling, retry logic, or when the user mentions domain errors, error recovery, error escalation.
1