Getting started
Requirements
gs-stack
is runtime-agnostic, meaning it works in the browser, in node, deno, bun etc.
Installation
To install gs-stack
, use your favourite node package manager:
- npm
- pnpm
- yarn
- bun
npm install gs-stack
pnpm install gs-stack
yarn add gs-stack
bun add gs-stack
Or directly from github using deno:
import { GSStack } from 'https://raw.githubusercontent.com/LaMavia/graph-structured-stack/main/src/index.ts'
Basics
What differentiates a graph-structured stack (GSS) from a regular stack is that its nodes can create a graph instead of a simple line. This allows for sharing common prefixes amongst multiple stacks, asymptotically saving memory. For instance, consider the following GSS containing four stacks, starting from the top: {7,3,1,0}
, {7,4,1,0}
, {7,5,2,0}
, and {8,6,2,0}
:
Using regular stacks in this case would require duplicating common stacks:
Pushing elements
Because new elements can extend any stack, it is necessary to supply the head node of the stack you want extend when pushing. When no head is provided, a new stack is created. For instance, let us implement the above GSS:
import { GSStack, GSSNode } from 'gs-stack'
const stack = new GSStack<number>()
const nodes: Record<number, GSSNode<number>> = {}
// {7,3,1,0}
nodes[0] = stack.push(0)
nodes[1] = stack.push(1, nodes[0])
nodes[3] = stack.push(3, nodes[1])
nodes[7] = stack.push(7, nodes[3])
// {7,4,1,0}
nodes[4] = stack.push(4, nodes[1])
nodes[7] = stack.push(7, nodes[4]) // 7 isn't duplicated, as it ends up in the same layer
// {7,5,2,0}
nodes[2] = stack.push(2, nodes[0])
nodes[5] = stack.push(5, nodes[2])
nodes[7] = stack.push(7, nodes[5])
// {8,6,2,0}
nodes[6] = stack.push(6, nodes[2])
nodes[8] = stack.push(8, nodes[6])
The constructor of GSStack
takes an optional comparator: (a: T, b: T) => boolean
function, which returns true
iff the two objects are considered "the same". By default, it is set to ===
.
When an item is pushed to a layer, it's checked whether a node with the same value already exists in there. If it does, push
returns a reference to said node with updated previous nodes; if it doesn't, a new node is created instead.
Popping elements
To pop an element, use the GSStack.pop(node: GSSNode<T>): boolean
method. It returns true
iff the element was successfully popped. Podding will fail if you supply a non-head node, meaning a node that has had values pushed on top of it.
WARNING: Once successfully popped, the node loses all of its previous node references, as nodes that are not bound to any stack should not be used in any way connected with a stack (ie. checking relations with other nodes). In practice, it means that you should get the previous nodes of a node before popping it.
To access the previous nodes of a given node use the GSSNode.prevSet(): GSSNode<T>[]
method.