Find a file
2023-08-27 21:14:18 +08:00
.idea Swap the positions of val and id to enhance the intuitiveness of the API. Revise the design of familyPosition in AbstractBinaryTree such that the previous assignment approach is replaced with a real-time retrieval method. Standardize the BST.remove method with the AbstractBinaryTree.remove method. Eliminate the redundant attribute name from TreeNode. 2023-08-26 10:24:31 +08:00
src Standardize methods for all BinaryTrees, enabling support for both TreeNode parameters and TreeNodeId as arguments. 2023-08-27 21:14:18 +08:00
tests/unit/data-structures Standardize methods for all BinaryTrees, enabling support for both TreeNode parameters and TreeNodeId as arguments. 2023-08-27 21:14:18 +08:00
.dependency-cruiser.js Circular dependencies check supported 2023-08-12 22:54:56 +08:00
.gitignore Successfully implemented recursive type inference for the BinaryTreeNode type by passing the node constructor through the constructor, effectively addressing the type inconsistency caused by invoking parent class methods after inheritance. 2023-08-22 22:50:16 +08:00
.npmignore Swap the positions of val and id to enhance the intuitiveness of the API. Revise the design of familyPosition in AbstractBinaryTree such that the previous assignment approach is replaced with a real-time retrieval method. Standardize the BST.remove method with the AbstractBinaryTree.remove method. Eliminate the redundant attribute name from TreeNode. 2023-08-26 10:24:31 +08:00
jest.config.js support test by using Jest 2023-08-12 01:11:08 +08:00
package-lock.json Swap the positions of val and id to enhance the intuitiveness of the API. Revise the design of familyPosition in AbstractBinaryTree such that the previous assignment approach is replaced with a real-time retrieval method. Standardize the BST.remove method with the AbstractBinaryTree.remove method. Eliminate the redundant attribute name from TreeNode. 2023-08-26 10:24:31 +08:00
package.json Swap the positions of val and id to enhance the intuitiveness of the API. Revise the design of familyPosition in AbstractBinaryTree such that the previous assignment approach is replaced with a real-time retrieval method. Standardize the BST.remove method with the AbstractBinaryTree.remove method. Eliminate the redundant attribute name from TreeNode. 2023-08-26 10:24:31 +08:00
README.md Successfully implemented recursive type inference for the BinaryTreeNode type by passing the node constructor through the constructor, effectively addressing the type inconsistency caused by invoking parent class methods after inheritance. 2023-08-22 22:50:16 +08:00
rename_clear_files.sh support test by using Jest 2023-08-12 01:11:08 +08:00
tsconfig.json Support TypeScript v5.1.6. Standardize all getters and setters. Adjust access permissions for accessors, set access permissions for protected or private member variables, and indicate them using the private identifier "_". 2023-08-21 16:17:01 +08:00

What

Brief

Javascript & TypeScript Data Structure Library.

Meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a wide range of data structures

Data Structures

Data Structure Unit Test Performance Test API Documentation Implemented
Binary Tree Binary Tree
Binary Search Tree (BST) BST
AVL Tree AVLTree
Tree Multiset TreeMultiSet
Segment Tree SegmentTree
Binary Indexed Tree BinaryIndexedTree
Graph AbstractGraph
Directed Graph DirectedGraph
Undirected Graph UndirectedGraph
Linked List SinglyLinkedList
Singly Linked List SinglyLinkedList
Doubly Linked List DoublyLinkedList
Queue Queue
Object Deque ObjectDeque
Array Deque ArrayDeque
Stack Stack
Coordinate Set CoordinateSet
Coordinate Map CoordinateMap
Heap Heap
Priority Queue PriorityQueue
Max Priority Queue MaxPriorityQueue
Min Priority Queue MinPriorityQueue
Trie Trie

Algorithms list only a few out, you can discover more in API docs

DFS, DFSIterative, BFS, morris, Bellman-Ford Algorithm, Dijkstra's Algorithm, Floyd-Warshall Algorithm, Tarjan's Algorithm

How

API Docs

Live Examples

Live Examples

install

yarn

yarn add data-structure-typed

npm

npm install data-structure-typed

Binary Search Tree (BST) snippet

    import {BST, BSTNode} from 'data-structure-typed';

    const tree = new BST();
    expect(tree).toBeInstanceOf(BST);

    const ids = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
    tree.addMany(ids);
    expect(tree.root).toBeInstanceOf(BSTNode);
    if (tree.root) expect(tree.root.id).toBe(11);
    expect(tree.count).toBe(16);
    expect(tree.has(6)).toBe(true);

    const node6 = tree.get(6);
    expect(node6 && tree.getHeight(node6)).toBe(2);
    expect(node6 && tree.getDepth(node6)).toBe(3);

    const nodeId10 = tree.get(10, 'id');
    expect(nodeId10?.id).toBe(10);

    const nodeVal9 = tree.get(9, 'val');
    expect(nodeVal9?.id).toBe(9);

    const nodesByCount1 = tree.getNodes(1, 'count');
    expect(nodesByCount1.length).toBe(16);

    const leftMost = tree.getLeftMost();
    expect(leftMost?.id).toBe(1);

    const node15 = tree.get(15);
    const minNodeBySpecificNode = node15 && tree.getLeftMost(node15);
    expect(minNodeBySpecificNode?.id).toBe(12);

    const subTreeSum = node15 && tree.subTreeSum(node15);
    expect(subTreeSum).toBe(70);

    const lesserSum = tree.lesserSum(10);
    expect(lesserSum).toBe(45);

    expect(node15).toBeInstanceOf(BSTNode);
    if (node15 instanceof BSTNode) {
        const subTreeAdd = tree.subTreeAdd(node15, 1, 'count');
        expect(subTreeAdd).toBeDefined();
    }

    const node11 = tree.get(11);
    expect(node11).toBeInstanceOf(BSTNode);
    if (node11 instanceof BSTNode) {
        const allGreaterNodesAdded = tree.allGreaterNodesAdd(node11, 2, 'count');
        expect(allGreaterNodesAdded).toBeDefined();
    }

    const dfsInorderNodes = tree.DFS('in', 'node');
    expect(dfsInorderNodes[0].id).toBe(1);
    expect(dfsInorderNodes[dfsInorderNodes.length - 1].id).toBe(16);

    tree.balance();
    expect(tree.isBalanced()).toBe(true);

    const bfsNodesAfterBalanced = tree.BFS('node');
    expect(bfsNodesAfterBalanced[0].id).toBe(8);
    expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].id).toBe(16);

    const removed11 = tree.remove(11, true);
    expect(removed11).toBeInstanceOf(Array);
    expect(removed11[0]).toBeDefined();
    expect(removed11[0].deleted).toBeDefined();

    if (removed11[0].deleted) expect(removed11[0].deleted.id).toBe(11);

    expect(tree.isAVLBalanced()).toBe(true);

    expect(node15 && tree.getHeight(node15)).toBe(2);

    const removed1 = tree.remove(1, true);
    expect(removed1).toBeInstanceOf(Array);
    expect(removed1[0]).toBeDefined();
    expect(removed1[0].deleted).toBeDefined();
    if (removed1[0].deleted) expect(removed1[0].deleted.id).toBe(1);

    expect(tree.isAVLBalanced()).toBe(true);

    expect(tree.getHeight()).toBe(4);

    // The code for removing these nodes (4, 10, 15, 5, 13, 3, 8, 6, 7, 9, 14) in sequence has been omitted.

    expect(tree.isAVLBalanced()).toBe(false);

    const bfsIDs = tree.BFS();
    expect(bfsIDs[0]).toBe(2);
    expect(bfsIDs[1]).toBe(12);
    expect(bfsIDs[2]).toBe(16);

    const bfsNodes = tree.BFS('node');
    expect(bfsNodes[0].id).toBe(2);
    expect(bfsNodes[1].id).toBe(12);
    expect(bfsNodes[2].id).toBe(16);

Directed Graph simple snippet

import {DirectedGraph, DirectedVertex, DirectedEdge, VertexId} from 'data-structure-typed';

let graph: DirectedGraph<DirectedVertex, DirectedEdge>;

    beforeEach(() => {
        graph = new DirectedGraph();
    });


    it('should add vertices', () => {
        const vertex1 = new DirectedVertex('A');
        const vertex2 = new DirectedVertex('B');

        graph.addVertex(vertex1);
        graph.addVertex(vertex2);

        expect(graph.hasVertex(vertex1)).toBe(true);
        expect(graph.hasVertex(vertex2)).toBe(true);
    });

    it('should add edges', () => {
        const vertex1 = new DirectedVertex('A');
        const vertex2 = new DirectedVertex('B');
        const edge = new DirectedEdge('A', 'B');

        graph.addVertex(vertex1);
        graph.addVertex(vertex2);
        graph.addEdge(edge);

        expect(graph.hasEdge('A', 'B')).toBe(true);
        expect(graph.hasEdge('B', 'A')).toBe(false);
    });

    it('should remove edges', () => {
        const vertex1 = new DirectedVertex('A');
        const vertex2 = new DirectedVertex('B');
        const edge = new DirectedEdge('A', 'B');

        graph.addVertex(vertex1);
        graph.addVertex(vertex2);
        graph.addEdge(edge);

        expect(graph.removeEdge(edge)).toBe(edge);
        expect(graph.hasEdge('A', 'B')).toBe(false);
    });

    it('should perform topological sort', () => {
        const vertexA = new DirectedVertex('A');
        const vertexB = new DirectedVertex('B');
        const vertexC = new DirectedVertex('C');
        const edgeAB = new DirectedEdge('A', 'B');
        const edgeBC = new DirectedEdge('B', 'C');

        graph.addVertex(vertexA);
        graph.addVertex(vertexB);
        graph.addVertex(vertexC);
        graph.addEdge(edgeAB);
        graph.addEdge(edgeBC);

        const topologicalOrder = graph.topologicalSort();
        if (topologicalOrder) expect(topologicalOrder.map(v => v.id)).toEqual(['A', 'B', 'C']);
    });

Directed Graph complex snippet

import {DirectedGraph, DirectedVertex, DirectedEdge, VertexId} from 'data-structure-typed';

class MyVertex extends DirectedVertex {
    private _data: string;
    get data(): string {
        return this._data;
    }
    set data(value: string) {
        this._data = value;
    }

    constructor(id: VertexId, data: string) {
        super(id);
        this._data = data;
    }
}

class MyEdge extends DirectedEdge {
    private _data: string;
    get data(): string {
        return this._data;
    }
    set data(value: string) {
        this._data = value;
    }

    constructor(v1: VertexId, v2: VertexId, weight: number, data: string) {
        super(v1, v2, weight);
        this._data = data;
    }
}

describe('DirectedGraph Test3', () => {
    const myGraph = new DirectedGraph<MyVertex, MyEdge>();

    it('should test graph operations', () => {
        const vertex1 = new MyVertex(1, 'data1');
        const vertex2 = new MyVertex(2, 'data2');
        const vertex3 = new MyVertex(3, 'data3');
        const vertex4 = new MyVertex(4, 'data4');
        const vertex5 = new MyVertex(5, 'data5');
        const vertex6 = new MyVertex(6, 'data6');
        const vertex7 = new MyVertex(7, 'data7');
        const vertex8 = new MyVertex(8, 'data8');
        const vertex9 = new MyVertex(9, 'data9');
        myGraph.addVertex(vertex1);
        myGraph.addVertex(vertex2);
        myGraph.addVertex(vertex3);
        myGraph.addVertex(vertex4);
        myGraph.addVertex(vertex5);
        myGraph.addVertex(vertex6);
        myGraph.addVertex(vertex7);
        myGraph.addVertex(vertex8);
        myGraph.addVertex(vertex9);

        myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
        myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1'));

        expect(myGraph.getEdge(1, 2)).toBeTruthy();
        expect(myGraph.getEdge(2, 1)).toBeTruthy();
        expect(myGraph.getEdge(1, '100')).toBeFalsy();

        myGraph.removeEdgeBetween(1, 2);
        expect(myGraph.getEdge(1, 2)).toBeFalsy();

        myGraph.addEdge(new MyEdge(3, 1, 3, 'edge-data-3-1'));
        myGraph.addEdge(new MyEdge(1, 9, 19, 'edge-data1-9'));
        myGraph.addEdge(new MyEdge(9, 7, 97, 'edge-data9-7'));
        myGraph.addEdge(new MyEdge(7, 9, 79, 'edge-data7-9'));
        myGraph.addEdge(new MyEdge(1, 4, 14, 'edge-data1-4'));
        myGraph.addEdge(new MyEdge(4, 7, 47, 'edge-data4-7'));
        myGraph.addEdge(new MyEdge(1, 2, 12, 'edge-data1-2'));
        myGraph.addEdge(new MyEdge(2, 3, 23, 'edge-data2-3'));
        myGraph.addEdge(new MyEdge(3, 5, 35, 'edge-data3-5'));
        myGraph.addEdge(new MyEdge(5, 7, 57, 'edge-data5-7'));
        myGraph.addEdge(new MyEdge(7, 3, 73, 'edge-data7-3'));
        
        const topologicalSorted = myGraph.topologicalSort();
        expect(topologicalSorted).toBeNull();

        const minPath1to7 = myGraph.getMinPathBetween(1, 7);
        expect(minPath1to7).toBeInstanceOf(Array);
        if (minPath1to7 && minPath1to7.length > 0) {
            expect(minPath1to7).toHaveLength(3);
            expect(minPath1to7[0]).toBeInstanceOf(MyVertex);
            expect(minPath1to7[0].id).toBe(1);
            expect(minPath1to7[1].id).toBe(9);
            expect(minPath1to7[2].id).toBe(7);
        }

        const fordResult1 = myGraph.bellmanFord(1);
        expect(fordResult1).toBeTruthy();
        expect(fordResult1.hasNegativeCycle).toBeUndefined();
        const {distMap, preMap, paths, min, minPath} = fordResult1;
        expect(distMap).toBeInstanceOf(Map);
        expect(distMap.size).toBe(9);
        expect(distMap.get(vertex1)).toBe(0);
        expect(distMap.get(vertex2)).toBe(12);
        expect(distMap.get(vertex3)).toBe(35);
        expect(distMap.get(vertex4)).toBe(14);
        expect(distMap.get(vertex5)).toBe(70);
        expect(distMap.get(vertex6)).toBe(Infinity);
        expect(distMap.get(vertex7)).toBe(61);
        expect(distMap.get(vertex8)).toBe(Infinity);
        expect(distMap.get(vertex9)).toBe(19);

        expect(preMap).toBeInstanceOf(Map);
        expect(preMap.size).toBe(0);

        expect(paths).toBeInstanceOf(Array);
        expect(paths.length).toBe(0);
        expect(min).toBe(Infinity);
        expect(minPath).toBeInstanceOf(Array);
        
        const floydResult = myGraph.floyd();
        expect(floydResult).toBeTruthy();
        if (floydResult) {
            const {costs, predecessor} = floydResult;
            expect(costs).toBeInstanceOf(Array);
            expect(costs.length).toBe(9);
            expect(costs[0]).toEqual([32, 12, 35, 14, 70, Infinity, 61, Infinity, 19]);
            expect(costs[1]).toEqual([20, 32, 23, 34, 58, Infinity, 81, Infinity, 39]);
            expect(costs[2]).toEqual([3, 15, 38, 17, 35, Infinity, 64, Infinity, 22]);
            expect(costs[3]).toEqual([123, 135, 120, 137, 155, Infinity, 47, Infinity, 126]);
            expect(costs[4]).toEqual([133, 145, 130, 147, 165, Infinity, 57, Infinity, 136]);
            expect(costs[5]).toEqual([Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity]);
            expect(costs[6]).toEqual([76, 88, 73, 90, 108, Infinity, 137, Infinity, 79]);
            expect(costs[7]).toEqual([Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity]);
            expect(costs[8]).toEqual([173, 185, 170, 187, 205, Infinity, 97, Infinity, 176]);

            expect(predecessor).toBeInstanceOf(Array);
            expect(predecessor.length).toBe(9);
            expect(predecessor[0]).toEqual([vertex2, null, vertex2, null, vertex3, null, vertex4, null, null]);
            expect(predecessor[1]).toEqual([null, vertex1, null, vertex1, vertex3, null, vertex4, null, vertex1]);
            expect(predecessor[5]).toEqual([null, null, null, null, null, null, null, null, null]);
            expect(predecessor[7]).toEqual([null, null, null, null, null, null, null, null, null]);
            expect(predecessor[8]).toEqual([vertex7, vertex7, vertex7, vertex7, vertex7, null, null, null, vertex7]);
        }

        const dijkstraRes12tt = myGraph.dijkstra(1, 2, true, true);
        expect(dijkstraRes12tt).toBeTruthy();
        if (dijkstraRes12tt) {
            const {distMap, minDist, minPath, paths, preMap, seen} = dijkstraRes12tt;
            expect(distMap).toBeInstanceOf(Map);
            expect(distMap.size).toBe(9);
            expect(distMap.get(vertex1)).toBe(0);
            expect(distMap.get(vertex2)).toBe(12);
            expect(distMap.get(vertex3)).toBe(Infinity);
            expect(distMap.get(vertex4)).toBe(14);
            expect(distMap.get(vertex5)).toBe(Infinity);
            expect(distMap.get(vertex6)).toBe(Infinity);
            expect(distMap.get(vertex7)).toBe(Infinity);
            expect(distMap.get(vertex8)).toBe(Infinity);
            expect(distMap.get(vertex9)).toBe(19);

            expect(minDist).toBe(12);
            expect(minPath).toBeInstanceOf(Array);
            expect(minPath.length).toBe(2);
            expect(minPath[0]).toBe(vertex1);
            expect(minPath[1]).toBe(vertex2);

            expect(paths).toBeInstanceOf(Array);
            expect(paths.length).toBe(9);
            expect(paths[0]).toBeInstanceOf(Array);
            expect(paths[0][0]).toBe(vertex1);

            expect(paths[1]).toBeInstanceOf(Array);
            expect(paths[1][0]).toBe(vertex1);
            expect(paths[1][1]).toBe(vertex2);

            expect(paths[2]).toBeInstanceOf(Array);
            expect(paths[2][0]).toBe(vertex3);
            expect(paths[3]).toBeInstanceOf(Array);
            expect(paths[3][0]).toBe(vertex1);
            expect(paths[3][1]).toBe(vertex4);
            expect(paths[4]).toBeInstanceOf(Array);
            expect(paths[4][0]).toBe(vertex5);

            expect(paths[5]).toBeInstanceOf(Array);
            expect(paths[5][0]).toBe(vertex6);
            expect(paths[6]).toBeInstanceOf(Array);
            expect(paths[6][0]).toBe(vertex7);
            expect(paths[7]).toBeInstanceOf(Array);
            expect(paths[7][0]).toBe(vertex8);
            expect(paths[8]).toBeInstanceOf(Array);
            expect(paths[8][0]).toBe(vertex1);
            expect(paths[8][1]).toBe(vertex9);
        }
    });
});

API docs

Examples Repository

Why

Complexities

performance of Big O

Big O Notation Type Computations for 10 elements Computations for 100 elements Computations for 1000 elements
O(1) Constant 1 1 1
O(log N) Logarithmic 3 6 9
O(N) Linear 10 100 1000
O(N log N) n log(n) 30 600 9000
O(N^2) Quadratic 100 10000 1000000
O(2^N) Exponential 1024 1.26e+29 1.07e+301
O(N!) Factorial 3628800 9.3e+157 4.02e+2567

Data Structure Complexity

Data Structure Access Search Insertion Deletion Comments
Array 1 n n n
Stack n n 1 1
Queue n n 1 1
Linked List n n 1 n
Hash Table - n n n In case of perfect hash function costs would be O(1)
Binary Search Tree n n n n In case of balanced tree costs would be O(log(n))
B-Tree log(n) log(n) log(n) log(n)
Red-Black Tree log(n) log(n) log(n) log(n)
AVL Tree log(n) log(n) log(n) log(n)
Bloom Filter - 1 1 - False positives are possible while searching

Sorting Complexity

Name Best Average Worst Memory Stable Comments
Bubble sort n n2 n2 1 Yes
Insertion sort n n2 n2 1 Yes
Selection sort n2 n2 n2 1 No
Heap sort n log(n) n log(n) n log(n) 1 No
Merge sort n log(n) n log(n) n log(n) n Yes
Quick sort n log(n) n log(n) n2 log(n) No Quicksort is usually done in-place with O(log(n)) stack space
Shell sort n log(n) depends on gap sequence n (log(n))2 1 No
Counting sort n + r n + r n + r n + r Yes r - biggest number in array
Radix sort n * k n * k n * k n + k Yes k - length of longest key

overview diagram

complexities

complexities of data structures