mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-09 23:54:04 +00:00
[project] github workflow added. eslint added. formating code by using prettier.
This commit is contained in:
parent
95b44f439b
commit
b263262a46
65
.eslintrc.js
Normal file
65
.eslintrc.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
module.exports = {
|
||||
'extends': [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier'
|
||||
],
|
||||
'rules': {
|
||||
'react/display-name': 'off',
|
||||
'@next/next/no-img-element': 'off',
|
||||
'react/no-unescaped-entities': 'off',
|
||||
'import/no-anonymous-default-export': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
// add new line above comment
|
||||
'lines-around-comment': [
|
||||
'error',
|
||||
{
|
||||
'beforeLineComment': false,
|
||||
'beforeBlockComment': true,
|
||||
'allowBlockStart': true,
|
||||
'allowClassStart': true,
|
||||
'allowObjectStart': true,
|
||||
'allowArrayStart': true
|
||||
}
|
||||
],
|
||||
// add new line above return
|
||||
'newline-before-return': 'off',
|
||||
// add new line below import
|
||||
'import/newline-after-import': [
|
||||
'error',
|
||||
{
|
||||
'count': 1
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/ban-types': [
|
||||
'error',
|
||||
{
|
||||
'extendDefaults': true,
|
||||
'types': {
|
||||
'{}': false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
'plugins': [
|
||||
'import'
|
||||
],
|
||||
'settings': {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': [
|
||||
'.ts',
|
||||
'.tsx'
|
||||
]
|
||||
},
|
||||
'import/resolver': {
|
||||
'typescript': {
|
||||
'alwaysTryTypes': true,
|
||||
'project': [
|
||||
'./tsconfig.json'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
{
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"react/display-name": "off",
|
||||
"@next/next/no-img-element": "off",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"import/no-anonymous-default-export": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
// add new line above comment
|
||||
"lines-around-comment": [
|
||||
"error",
|
||||
{
|
||||
"beforeLineComment": false,
|
||||
"beforeBlockComment": true,
|
||||
"allowBlockStart": true,
|
||||
"allowClassStart": true,
|
||||
"allowObjectStart": true,
|
||||
"allowArrayStart": true
|
||||
}
|
||||
],
|
||||
// add new line above return
|
||||
"newline-before-return": "off",
|
||||
// add new line below import
|
||||
"import/newline-after-import": [
|
||||
"error",
|
||||
{
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
"extendDefaults": true,
|
||||
"types": {
|
||||
"{}": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"import"
|
||||
],
|
||||
"settings": {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [
|
||||
".ts",
|
||||
".tsx"
|
||||
]
|
||||
},
|
||||
"import/resolver": {
|
||||
"typescript": {
|
||||
"alwaysTryTypes": true,
|
||||
"project": [
|
||||
"./tsconfig.json"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
.github/workflows/ci.yml
vendored
Normal file
28
.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 19
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
6
.prettierignore
Normal file
6
.prettierignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
src/types/data-structures/abstract-binary-tree.ts
|
||||
src/types/data-structures/binary-tree.ts
|
||||
src/types/data-structures/bst.ts
|
||||
src/types/data-structures/avl-tree.ts
|
||||
src/types/data-structures/tree-multiset.ts
|
||||
src/types/data-structures/rb-tree.ts
|
16
.prettierrc.js
Normal file
16
.prettierrc.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
module.exports = {
|
||||
arrowParens: 'avoid',
|
||||
bracketSpacing: true,
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
insertPragma: false,
|
||||
bracketSameLine: false,
|
||||
jsxSingleQuote: true,
|
||||
printWidth: 120,
|
||||
proseWrap: 'preserve',
|
||||
quoteProps: 'as-needed',
|
||||
requirePragma: false,
|
||||
singleQuote: true,
|
||||
tabWidth: 2,
|
||||
trailingComma: 'none',
|
||||
useTabs: false
|
||||
}
|
16
package.json
16
package.json
|
@ -2,9 +2,9 @@
|
|||
"name": "data-structure-typed",
|
||||
"version": "1.3.6",
|
||||
"description": "Data Structures of Javascript & TypeScript. AVLTree, Binary Search Tree, Binary Tree, Tree Multiset, Graph, Heap, Priority Queue, Linked List.",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"main": "lib/index.js",
|
||||
"module": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && npx tsc && npm run build:browser",
|
||||
"build:browser": "webpack",
|
||||
|
@ -146,11 +146,6 @@
|
|||
"deque-typed": "^1.3.3",
|
||||
"directed-graph-typed": "^1.3.3",
|
||||
"doubly-linked-list-typed": "^1.3.3",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"graph-typed": "^1.3.3",
|
||||
"heap-typed": "^1.3.3",
|
||||
"jest": "^29.6.2",
|
||||
|
@ -159,6 +154,11 @@
|
|||
"max-priority-queue-typed": "^1.3.3",
|
||||
"min-heap-typed": "^1.3.3",
|
||||
"min-priority-queue-typed": "^1.3.3",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"prettier": "^3.0.3",
|
||||
"priority-queue-typed": "^1.3.3",
|
||||
"queue-typed": "^1.3.3",
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class AaTree {
|
||||
|
||||
}
|
||||
export class AaTree {}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import {trampoline} from '../../utils';
|
||||
import { trampoline } from '../../utils';
|
||||
import type {
|
||||
AbstractBinaryTreeNodeNested,
|
||||
AbstractBinaryTreeNodeProperties,
|
||||
|
@ -17,11 +17,14 @@ import type {
|
|||
DFSOrderPattern,
|
||||
NodeOrPropertyName
|
||||
} from '../../types';
|
||||
import {AbstractBinaryTreeOptions, FamilyPosition, LoopType} from '../../types';
|
||||
import {IAbstractBinaryTree, IAbstractBinaryTreeNode} from '../../interfaces';
|
||||
|
||||
export abstract class AbstractBinaryTreeNode<T = any, NEIGHBOR extends AbstractBinaryTreeNode<T, NEIGHBOR> = AbstractBinaryTreeNodeNested<T>> implements IAbstractBinaryTreeNode<T, NEIGHBOR> {
|
||||
import { AbstractBinaryTreeOptions, FamilyPosition, LoopType } from '../../types';
|
||||
import { IAbstractBinaryTree, IAbstractBinaryTreeNode } from '../../interfaces';
|
||||
|
||||
export abstract class AbstractBinaryTreeNode<
|
||||
T = any,
|
||||
NEIGHBOR extends AbstractBinaryTreeNode<T, NEIGHBOR> = AbstractBinaryTreeNodeNested<T>
|
||||
> implements IAbstractBinaryTreeNode<T, NEIGHBOR>
|
||||
{
|
||||
/**
|
||||
* The constructor function initializes a BinaryTreeNode object with an id and an optional value.
|
||||
* @param {BinaryTreeNodeId} id - The `id` parameter is of type `BinaryTreeNodeId` and represents the unique identifier
|
||||
|
@ -132,8 +135,9 @@ export abstract class AbstractBinaryTreeNode<T = any, NEIGHBOR extends AbstractB
|
|||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'], N> = AbstractBinaryTreeNode> implements IAbstractBinaryTree<N> {
|
||||
|
||||
export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'], N> = AbstractBinaryTreeNode>
|
||||
implements IAbstractBinaryTree<N>
|
||||
{
|
||||
/**
|
||||
* The protected constructor initializes the options for an abstract binary tree.
|
||||
* @param {AbstractBinaryTreeOptions} [options] - An optional object that contains configuration options for the binary
|
||||
|
@ -141,7 +145,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
*/
|
||||
protected constructor(options?: AbstractBinaryTreeOptions) {
|
||||
if (options !== undefined) {
|
||||
const {loopType = LoopType.ITERATIVE} = options;
|
||||
const { loopType = LoopType.ITERATIVE } = options;
|
||||
this._loopType = loopType;
|
||||
}
|
||||
this.clear();
|
||||
|
@ -189,7 +193,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return this._visitedLeftSum;
|
||||
}
|
||||
|
||||
abstract createNode(id: BinaryTreeNodeId, val?: N['val']): N | null ;
|
||||
abstract createNode(id: BinaryTreeNodeId, val?: N['val']): N | null;
|
||||
|
||||
/**
|
||||
* The `swapLocation` function swaps the location of two nodes in a binary tree.
|
||||
|
@ -199,7 +203,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* @returns The `destNode` is being returned.
|
||||
*/
|
||||
swapLocation(srcNode: N, destNode: N): N {
|
||||
const {id, val, height} = destNode;
|
||||
const { id, val, height } = destNode;
|
||||
const tempNode = this.createNode(id, val);
|
||||
|
||||
if (tempNode) {
|
||||
|
@ -297,7 +301,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return inserted;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The `addMany` function takes an array of binary tree node IDs or nodes, and optionally an array of corresponding data
|
||||
* values, and adds them to the binary tree.
|
||||
|
@ -344,7 +347,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return idsOrNodes.length === this.addMany(idsOrNodes, data).length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The `remove` function removes a node from a binary search tree and returns the deleted node along with the parent node
|
||||
* that needs to be balanced.
|
||||
|
@ -356,7 +358,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* @returns The function `remove` returns an array of `BinaryTreeDeletedResult<N>` objects.
|
||||
*/
|
||||
remove(nodeOrId: N | BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): BinaryTreeDeletedResult<N>[] {
|
||||
|
||||
isUpdateAllLeftSum = isUpdateAllLeftSum === undefined ? true : isUpdateAllLeftSum;
|
||||
// TODO may implement update all left sum
|
||||
if (isUpdateAllLeftSum) {
|
||||
|
@ -365,17 +366,18 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
|
||||
if (!this.root) return bstDeletedResult;
|
||||
|
||||
const curr: N | null = (typeof nodeOrId === 'number') ? this.get(nodeOrId) : nodeOrId;
|
||||
const curr: N | null = typeof nodeOrId === 'number' ? this.get(nodeOrId) : nodeOrId;
|
||||
if (!curr) return bstDeletedResult;
|
||||
|
||||
const parent: N | null = curr?.parent ? curr.parent : null;
|
||||
let needBalanced: N | null = null, orgCurrent = curr;
|
||||
let needBalanced: N | null = null,
|
||||
orgCurrent = curr;
|
||||
|
||||
if (!curr.left) {
|
||||
if (!parent) {
|
||||
if (curr.right !== undefined) this._setRoot(curr.right);
|
||||
} else {
|
||||
const {familyPosition: fp} = curr;
|
||||
const { familyPosition: fp } = curr;
|
||||
if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
|
||||
parent.left = curr.right;
|
||||
} else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
|
||||
|
@ -389,7 +391,8 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
||||
orgCurrent = this.swapLocation(curr, leftSubTreeRightMost);
|
||||
if (parentOfLeftSubTreeMax) {
|
||||
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
||||
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
|
||||
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
||||
else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
|
||||
needBalanced = parentOfLeftSubTreeMax;
|
||||
}
|
||||
|
@ -397,7 +400,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
}
|
||||
this._setSize(this.size - 1);
|
||||
|
||||
bstDeletedResult.push({deleted: orgCurrent, needBalanced});
|
||||
bstDeletedResult.push({ deleted: orgCurrent, needBalanced });
|
||||
return bstDeletedResult;
|
||||
}
|
||||
|
||||
|
@ -444,18 +447,18 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return -1;
|
||||
}
|
||||
|
||||
const stack: { node: N; depth: number }[] = [{node: beginRoot, depth: 0}];
|
||||
const stack: { node: N; depth: number }[] = [{ node: beginRoot, depth: 0 }];
|
||||
let maxHeight = 0;
|
||||
|
||||
while (stack.length > 0) {
|
||||
const {node, depth} = stack.pop()!;
|
||||
const { node, depth } = stack.pop()!;
|
||||
|
||||
if (node.left) {
|
||||
stack.push({node: node.left, depth: depth + 1});
|
||||
stack.push({ node: node.left, depth: depth + 1 });
|
||||
}
|
||||
|
||||
if (node.right) {
|
||||
stack.push({node: node.right, depth: depth + 1});
|
||||
stack.push({ node: node.right, depth: depth + 1 });
|
||||
}
|
||||
|
||||
maxHeight = Math.max(maxHeight, depth);
|
||||
|
@ -489,7 +492,8 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return _getMinHeight(beginRoot);
|
||||
} else {
|
||||
const stack: N[] = [];
|
||||
let node: N | null | undefined = beginRoot, last: N | null = null;
|
||||
let node: N | null | undefined = beginRoot,
|
||||
last: N | null = null;
|
||||
const depths: Map<N, number> = new Map();
|
||||
|
||||
while (stack.length > 0 || node) {
|
||||
|
@ -497,7 +501,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
stack.push(node);
|
||||
node = node.left;
|
||||
} else {
|
||||
node = stack[stack.length - 1]
|
||||
node = stack[stack.length - 1];
|
||||
if (!node.right || last === node.right) {
|
||||
node = stack.pop();
|
||||
if (node) {
|
||||
|
@ -507,7 +511,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
last = node;
|
||||
node = null;
|
||||
}
|
||||
} else node = node.right
|
||||
} else node = node.right;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,7 +527,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* @returns The method is returning a boolean value.
|
||||
*/
|
||||
isPerfectlyBalanced(beginRoot?: N | null): boolean {
|
||||
return (this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot));
|
||||
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -537,7 +541,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* function will stop traversing the tree and return the first matching node. If `only
|
||||
* @returns an array of nodes (type N).
|
||||
*/
|
||||
getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean): N[] {
|
||||
getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName, onlyOne?: boolean): N[] {
|
||||
if (!this.root) return [];
|
||||
propertyName = propertyName ?? 'id';
|
||||
|
||||
|
@ -549,7 +553,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
if (!cur.left && !cur.right) return;
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(this.root);
|
||||
} else {
|
||||
|
@ -575,7 +579,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* specifies the name of the property to be checked in the nodes. If not provided, it defaults to 'id'.
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
has(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): boolean {
|
||||
has(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName): boolean {
|
||||
propertyName = propertyName ?? 'id';
|
||||
// TODO may support finding node by value equal
|
||||
return this.getNodes(nodeProperty, propertyName).length > 0;
|
||||
|
@ -592,7 +596,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* @returns either the value of the specified property of the node, or the node itself if no property name is provided.
|
||||
* If no matching node is found, it returns null.
|
||||
*/
|
||||
get(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): N | null {
|
||||
get(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName): N | null {
|
||||
propertyName = propertyName ?? 'id';
|
||||
// TODO may support finding node by value equal
|
||||
return this.getNodes(nodeProperty, propertyName, true)[0] ?? null;
|
||||
|
@ -642,11 +646,10 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
if (!beginRoot) return beginRoot;
|
||||
|
||||
if (this._loopType === LoopType.RECURSIVE) {
|
||||
|
||||
const _traverse = (cur: N): N => {
|
||||
if (!cur.left) return cur;
|
||||
return _traverse(cur.left);
|
||||
}
|
||||
};
|
||||
|
||||
return _traverse(beginRoot);
|
||||
} else {
|
||||
|
@ -683,7 +686,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
const _traverse = (cur: N): N => {
|
||||
if (!cur.right) return cur;
|
||||
return _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
return _traverse(node);
|
||||
} else {
|
||||
|
@ -711,19 +714,20 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
if (!cur) return true;
|
||||
if (cur.id <= min || cur.id >= max) return false;
|
||||
return dfs(cur.left, min, cur.id) && dfs(cur.right, cur.id, max);
|
||||
}
|
||||
};
|
||||
|
||||
return dfs(node, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
||||
} else {
|
||||
const stack = [];
|
||||
let prev = Number.MIN_SAFE_INTEGER, curr: N | null | undefined = node;
|
||||
let prev = Number.MIN_SAFE_INTEGER,
|
||||
curr: N | null | undefined = node;
|
||||
while (curr || stack.length > 0) {
|
||||
while (curr) {
|
||||
stack.push(curr);
|
||||
curr = curr.left;
|
||||
}
|
||||
curr = stack.pop()!;
|
||||
if (!(curr) || prev >= curr.id) return false;
|
||||
if (!curr || prev >= curr.id) return false;
|
||||
prev = curr.id;
|
||||
curr = curr.right;
|
||||
}
|
||||
|
@ -755,7 +759,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
size++;
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(subTreeRoot);
|
||||
return size;
|
||||
|
@ -782,7 +786,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* not provided, it defaults to 'id'.
|
||||
* @returns a number, which is the sum of the values of the specified property in the subtree rooted at `subTreeRoot`.
|
||||
*/
|
||||
subTreeSum(subTreeRoot: N | BinaryTreeNodeId | null, propertyName ?: BinaryTreeNodePropertyName): number {
|
||||
subTreeSum(subTreeRoot: N | BinaryTreeNodeId | null, propertyName?: BinaryTreeNodePropertyName): number {
|
||||
propertyName = propertyName ?? 'id';
|
||||
if (typeof subTreeRoot === 'number') subTreeRoot = this.get(subTreeRoot, 'id');
|
||||
|
||||
|
@ -804,14 +808,14 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
break;
|
||||
}
|
||||
return needSum;
|
||||
}
|
||||
};
|
||||
|
||||
if (this._loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (cur: N): void => {
|
||||
sum += _sumByProperty(cur);
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(subTreeRoot);
|
||||
} else {
|
||||
|
@ -838,7 +842,11 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* specifies the property of the binary tree node that should be modified. If not provided, it defaults to 'id'.
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
subTreeAdd(subTreeRoot: N | BinaryTreeNodeId | null, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean {
|
||||
subTreeAdd(
|
||||
subTreeRoot: N | BinaryTreeNodeId | null,
|
||||
delta: number,
|
||||
propertyName?: BinaryTreeNodePropertyName
|
||||
): boolean {
|
||||
propertyName = propertyName ?? 'id';
|
||||
if (typeof subTreeRoot === 'number') subTreeRoot = this.get(subTreeRoot, 'id');
|
||||
|
||||
|
@ -853,7 +861,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
cur.id += delta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this._loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (cur: N) => {
|
||||
|
@ -894,7 +902,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* the
|
||||
* @returns an instance of the `AbstractBinaryTreeNodeProperties` class with generic type `N`.
|
||||
*/
|
||||
BFS(nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
BFS(nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
nodeOrPropertyName = nodeOrPropertyName ?? 'id';
|
||||
this._clearResults();
|
||||
const queue: Array<N | null | undefined> = [this.root];
|
||||
|
@ -930,7 +938,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* @returns an instance of the AbstractBinaryTreeNodeProperties class, which contains the accumulated properties of the
|
||||
* binary tree nodes based on the specified pattern and node or property name.
|
||||
*/
|
||||
DFS(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
DFS(pattern?: 'in' | 'pre' | 'post', nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
pattern = pattern ?? 'in';
|
||||
nodeOrPropertyName = nodeOrPropertyName ?? 'id';
|
||||
this._clearResults();
|
||||
|
@ -960,7 +968,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
|
||||
DFSIterative(): BinaryTreeNodeId[];
|
||||
|
||||
|
||||
// --- start additional methods ---
|
||||
|
||||
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
|
||||
|
@ -980,13 +987,16 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* the
|
||||
* @returns an object of type AbstractBinaryTreeNodeProperties<N>.
|
||||
*/
|
||||
DFSIterative(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
DFSIterative(
|
||||
pattern?: 'in' | 'pre' | 'post',
|
||||
nodeOrPropertyName?: NodeOrPropertyName
|
||||
): AbstractBinaryTreeNodeProperties<N> {
|
||||
pattern = pattern || 'in';
|
||||
nodeOrPropertyName = nodeOrPropertyName || 'id';
|
||||
this._clearResults();
|
||||
if (!this.root) return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
// 0: visit, 1: print
|
||||
const stack: { opt: 0 | 1, node: N | null | undefined }[] = [{opt: 0, node: this.root}];
|
||||
const stack: { opt: 0 | 1; node: N | null | undefined }[] = [{ opt: 0, node: this.root }];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const cur = stack.pop();
|
||||
|
@ -996,24 +1006,24 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
} else {
|
||||
switch (pattern) {
|
||||
case 'in':
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
stack.push({ opt: 0, node: cur.node.right });
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
stack.push({ opt: 0, node: cur.node.left });
|
||||
break;
|
||||
case 'pre':
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({ opt: 0, node: cur.node.right });
|
||||
stack.push({ opt: 0, node: cur.node.left });
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
break;
|
||||
case 'post':
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
stack.push({ opt: 0, node: cur.node.right });
|
||||
stack.push({ opt: 0, node: cur.node.left });
|
||||
break;
|
||||
default:
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
stack.push({ opt: 0, node: cur.node.right });
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
stack.push({ opt: 0, node: cur.node.left });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1042,7 +1052,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* accumulating results
|
||||
* @returns The function `levelIterative` returns an object of type `AbstractBinaryTreeNodeProperties<N>`.
|
||||
*/
|
||||
levelIterative(node: N | null, nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
levelIterative(node: N | null, nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
nodeOrPropertyName = nodeOrPropertyName || 'id';
|
||||
node = node || this.root;
|
||||
if (!node) return [];
|
||||
|
@ -1105,7 +1115,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
levelsNodes[level].push(node.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.loopType === LoopType.RECURSIVE) {
|
||||
const _recursive = (node: N, level: number) => {
|
||||
|
@ -1141,7 +1151,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
getPredecessor(node: N): N {
|
||||
if (node.left) {
|
||||
let predecessor: N | null | undefined = node.left;
|
||||
while (!(predecessor) || predecessor.right && predecessor.right !== node) {
|
||||
while (!predecessor || (predecessor.right && predecessor.right !== node)) {
|
||||
if (predecessor) {
|
||||
predecessor = predecessor.right;
|
||||
}
|
||||
|
@ -1175,7 +1185,10 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* tree.
|
||||
* @returns an array of AbstractBinaryTreeNodeProperties<N> objects.
|
||||
*/
|
||||
morris(pattern?: 'in' | 'pre' | 'post', nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
morris(
|
||||
pattern?: 'in' | 'pre' | 'post',
|
||||
nodeOrPropertyName?: NodeOrPropertyName
|
||||
): AbstractBinaryTreeNodeProperties<N> {
|
||||
if (this.root === null) return [];
|
||||
|
||||
pattern = pattern || 'in';
|
||||
|
@ -1335,7 +1348,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
this._visitedLeftSum = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The function sets the root property of an object to a given value, and if the value is not null, it also sets the
|
||||
* parent property of the value to undefined.
|
||||
|
@ -1382,7 +1394,13 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* `true`, the function will stop after finding the first matching node and return `true`. If `onlyOne
|
||||
* @returns a boolean value indicating whether only one matching node should be pushed into the result array.
|
||||
*/
|
||||
protected _pushByPropertyNameStopOrNot(cur: N, result: (N | null | undefined)[], nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
|
||||
protected _pushByPropertyNameStopOrNot(
|
||||
cur: N,
|
||||
result: (N | null | undefined)[],
|
||||
nodeProperty: BinaryTreeNodeId | N,
|
||||
propertyName?: BinaryTreeNodePropertyName,
|
||||
onlyOne?: boolean
|
||||
) {
|
||||
switch (propertyName) {
|
||||
case 'id':
|
||||
if (cur.id === nodeProperty) {
|
||||
|
@ -1412,7 +1430,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* can be either a string representing a property name or a reference to a `Node` object. If it is a string, it
|
||||
* specifies the property name to be used for accumulating values. If it is a `Node` object, it specifies
|
||||
*/
|
||||
protected _accumulatedByPropertyName(node: N, nodeOrPropertyName ?: NodeOrPropertyName) {
|
||||
protected _accumulatedByPropertyName(node: N, nodeOrPropertyName?: NodeOrPropertyName) {
|
||||
nodeOrPropertyName = nodeOrPropertyName ?? 'id';
|
||||
|
||||
switch (nodeOrPropertyName) {
|
||||
|
@ -1443,7 +1461,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
* can accept either a `NodeOrPropertyName` type or be undefined.
|
||||
* @returns The method `_getResultByPropertyName` returns an instance of `AbstractBinaryTreeNodeProperties<N>`.
|
||||
*/
|
||||
protected _getResultByPropertyName(nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
protected _getResultByPropertyName(nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N> {
|
||||
nodeOrPropertyName = nodeOrPropertyName ?? 'id';
|
||||
|
||||
switch (nodeOrPropertyName) {
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {BST, BSTNode} from './bst';
|
||||
import type {AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BinaryTreeNodeId} from '../../types';
|
||||
import {IAVLTree, IAVLTreeNode} from '../../interfaces';
|
||||
import { BST, BSTNode } from './bst';
|
||||
import type { AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BinaryTreeNodeId } from '../../types';
|
||||
import { IAVLTree, IAVLTreeNode } from '../../interfaces';
|
||||
|
||||
export class AVLTreeNode<T = any, NEIGHBOR extends AVLTreeNode<T, NEIGHBOR> = AVLTreeNodeNested<T>> extends BSTNode<T, NEIGHBOR> implements IAVLTreeNode<T, NEIGHBOR> {
|
||||
export class AVLTreeNode<T = any, NEIGHBOR extends AVLTreeNode<T, NEIGHBOR> = AVLTreeNodeNested<T>>
|
||||
extends BSTNode<T, NEIGHBOR>
|
||||
implements IAVLTreeNode<T, NEIGHBOR>
|
||||
{
|
||||
constructor(id: BinaryTreeNodeId, val?: T) {
|
||||
super(id, val);
|
||||
}
|
||||
|
@ -64,7 +67,7 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
*/
|
||||
override remove(id: BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): BinaryTreeDeletedResult<N>[] {
|
||||
const deletedResults = super.remove(id, isUpdateAllLeftSum);
|
||||
for (const {needBalanced} of deletedResults) {
|
||||
for (const { needBalanced } of deletedResults) {
|
||||
if (needBalanced) {
|
||||
this._balancePath(needBalanced);
|
||||
}
|
||||
|
@ -79,12 +82,13 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
* @returns The balance factor of the given AVL tree node.
|
||||
*/
|
||||
protected _balanceFactor(node: N): number {
|
||||
if (!node.right) // node has no right subtree
|
||||
if (!node.right)
|
||||
// node has no right subtree
|
||||
return -node.height;
|
||||
else if (!node.left) // node has no left subtree
|
||||
else if (!node.left)
|
||||
// node has no left subtree
|
||||
return +node.height;
|
||||
else
|
||||
return node.right.height - node.left.height;
|
||||
else return node.right.height - node.left.height;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,15 +96,12 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
* @param node - The parameter `node` is an AVLTreeNode object, which represents a node in an AVL tree.
|
||||
*/
|
||||
protected _updateHeight(node: N): void {
|
||||
if (!node.left && !node.right)
|
||||
node.height = 0;
|
||||
if (!node.left && !node.right) node.height = 0;
|
||||
else if (!node.left) {
|
||||
const rightHeight = node.right ? node.right.height : 0;
|
||||
node.height = 1 + rightHeight;
|
||||
} else if (!node.right)
|
||||
node.height = 1 + node.left.height;
|
||||
else
|
||||
node.height = 1 + Math.max(node.right.height, node.left.height);
|
||||
} else if (!node.right) node.height = 1 + node.left.height;
|
||||
else node.height = 1 + Math.max(node.right.height, node.left.height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,18 +110,21 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
* @param node - The `node` parameter is an AVLTreeNode object, which represents a node in an AVL tree.
|
||||
*/
|
||||
protected _balancePath(node: N): void {
|
||||
|
||||
const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
|
||||
for (let i = 0; i < path.length; i++) { // second O(log n)
|
||||
const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
// second O(log n)
|
||||
const A = path[i];
|
||||
// Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
|
||||
this._updateHeight(A); // first O(1)
|
||||
this._updateHeight(A); // first O(1)
|
||||
// Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
|
||||
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
|
||||
switch (this._balanceFactor(A)) { // second O(1)
|
||||
switch (
|
||||
this._balanceFactor(A) // second O(1)
|
||||
) {
|
||||
case -2:
|
||||
if (A && A.left) {
|
||||
if (this._balanceFactor(A.left) <= 0) { // second O(1)
|
||||
if (this._balanceFactor(A.left) <= 0) {
|
||||
// second O(1)
|
||||
// Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
|
||||
this._balanceLL(A);
|
||||
} else {
|
||||
|
@ -282,7 +286,6 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
C.parent = parentOfA;
|
||||
}
|
||||
|
||||
|
||||
if (A === this.root) {
|
||||
if (C) this._setRoot(C);
|
||||
} else {
|
||||
|
@ -305,5 +308,3 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
C && this._updateHeight(C);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class BTree {
|
||||
|
||||
}
|
||||
export class BTree {}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
export class BinaryIndexedTree {
|
||||
|
||||
/**
|
||||
* The constructor initializes an array with a specified length and fills it with zeros.
|
||||
* @param {number} n - The parameter `n` represents the size of the array that will be used to store the sum tree. The
|
||||
|
@ -24,7 +23,7 @@ export class BinaryIndexedTree {
|
|||
}
|
||||
|
||||
static lowBit(x: number) {
|
||||
return x & (-x);
|
||||
return x & -x;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,8 +66,7 @@ export class BinaryIndexedTree {
|
|||
* @returns the sum of the elements in the range specified by the start and end indices.
|
||||
*/
|
||||
getRangeSum(start: number, end: number): number {
|
||||
if (!(0 <= start && start <= end && end <= this._sumTree.length))
|
||||
throw 'Index out of bounds';
|
||||
if (!(0 <= start && start <= end && end <= this._sumTree.length)) throw 'Index out of bounds';
|
||||
return this.getPrefixSum(end) - this.getPrefixSum(start);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,18 +6,23 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import type {BinaryTreeNodeId, BinaryTreeNodeNested, BinaryTreeOptions} from '../../types';
|
||||
import {AbstractBinaryTree, AbstractBinaryTreeNode} from './abstract-binary-tree';
|
||||
import {IBinaryTree, IBinaryTreeNode} from '../../interfaces';
|
||||
import type { BinaryTreeNodeId, BinaryTreeNodeNested, BinaryTreeOptions } from '../../types';
|
||||
import { AbstractBinaryTree, AbstractBinaryTreeNode } from './abstract-binary-tree';
|
||||
import { IBinaryTree, IBinaryTreeNode } from '../../interfaces';
|
||||
|
||||
export class BinaryTreeNode<T = any, NEIGHBOR extends BinaryTreeNode<T, NEIGHBOR> = BinaryTreeNodeNested<T>> extends AbstractBinaryTreeNode<T, NEIGHBOR> implements IBinaryTreeNode<T, NEIGHBOR> {
|
||||
export class BinaryTreeNode<T = any, NEIGHBOR extends BinaryTreeNode<T, NEIGHBOR> = BinaryTreeNodeNested<T>>
|
||||
extends AbstractBinaryTreeNode<T, NEIGHBOR>
|
||||
implements IBinaryTreeNode<T, NEIGHBOR>
|
||||
{
|
||||
constructor(id: BinaryTreeNodeId, val?: T) {
|
||||
super(id, val);
|
||||
}
|
||||
}
|
||||
|
||||
export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode> extends AbstractBinaryTree<N> implements IBinaryTree<N> {
|
||||
|
||||
export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
||||
extends AbstractBinaryTree<N>
|
||||
implements IBinaryTree<N>
|
||||
{
|
||||
/**
|
||||
* This is a constructor function for a binary tree class that takes an optional options parameter.
|
||||
* @param {BinaryTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the
|
||||
|
|
|
@ -5,12 +5,21 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type {BinaryTreeNodeId, BinaryTreeNodePropertyName, BSTComparator, BSTNodeNested, BSTOptions} from '../../types';
|
||||
import {CP, LoopType} from '../../types';
|
||||
import {BinaryTree, BinaryTreeNode} from './binary-tree';
|
||||
import {IBST, IBSTNode} from '../../interfaces';
|
||||
import type {
|
||||
BinaryTreeNodeId,
|
||||
BinaryTreeNodePropertyName,
|
||||
BSTComparator,
|
||||
BSTNodeNested,
|
||||
BSTOptions
|
||||
} from '../../types';
|
||||
import { CP, LoopType } from '../../types';
|
||||
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
||||
import { IBST, IBSTNode } from '../../interfaces';
|
||||
|
||||
export class BSTNode<T = any, NEIGHBOR extends BSTNode<T, NEIGHBOR> = BSTNodeNested<T>> extends BinaryTreeNode<T, NEIGHBOR> implements IBSTNode<T, NEIGHBOR> {
|
||||
export class BSTNode<T = any, NEIGHBOR extends BSTNode<T, NEIGHBOR> = BSTNodeNested<T>>
|
||||
extends BinaryTreeNode<T, NEIGHBOR>
|
||||
implements IBSTNode<T, NEIGHBOR>
|
||||
{
|
||||
constructor(id: BinaryTreeNodeId, val?: T) {
|
||||
super(id, val);
|
||||
}
|
||||
|
@ -24,7 +33,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
constructor(options?: BSTOptions) {
|
||||
super(options);
|
||||
if (options !== undefined) {
|
||||
const {comparator} = options;
|
||||
const { comparator } = options;
|
||||
if (comparator !== undefined) {
|
||||
this._comparator = comparator;
|
||||
}
|
||||
|
@ -66,7 +75,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
if (this.root === null) {
|
||||
this._setRoot(newNode);
|
||||
this._setSize(this.size + 1);
|
||||
inserted = (this.root);
|
||||
inserted = this.root;
|
||||
} else {
|
||||
let cur = this.root;
|
||||
let traversing = true;
|
||||
|
@ -104,7 +113,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
cur.right = newNode;
|
||||
this._setSize(this.size + 1);
|
||||
traversing = false;
|
||||
inserted = (cur.right);
|
||||
inserted = cur.right;
|
||||
} else {
|
||||
//Traverse the left of the current node
|
||||
if (cur.right) cur = cur.right;
|
||||
|
@ -128,35 +137,40 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
* @param {boolean} isBalanceAdd - If true the nodes will be balance inserted in binary search method.
|
||||
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
|
||||
*/
|
||||
override addMany(idsOrNodes: (BinaryTreeNodeId | null)[] | (N | null)[], data?: N['val'][], isBalanceAdd = false): (N | null | undefined)[] {
|
||||
function hasNoNull (arr: (BinaryTreeNodeId | null)[] | (N | null)[]): arr is BinaryTreeNodeId[] | N[] {
|
||||
override addMany(
|
||||
idsOrNodes: (BinaryTreeNodeId | null)[] | (N | null)[],
|
||||
data?: N['val'][],
|
||||
isBalanceAdd = false
|
||||
): (N | null | undefined)[] {
|
||||
function hasNoNull(arr: (BinaryTreeNodeId | null)[] | (N | null)[]): arr is BinaryTreeNodeId[] | N[] {
|
||||
return arr.indexOf(null) === -1;
|
||||
}
|
||||
if (!isBalanceAdd || !hasNoNull(idsOrNodes)) {
|
||||
return super.addMany(idsOrNodes, data);
|
||||
}
|
||||
const inserted: (N | null | undefined)[] = [];
|
||||
const combinedArr: [BinaryTreeNodeId | N , N['val']][] = idsOrNodes.map((value, index) => [value, data?.[index]]);
|
||||
const combinedArr: [BinaryTreeNodeId | N, N['val']][] = idsOrNodes.map((value, index) => [value, data?.[index]]);
|
||||
let sorted = [];
|
||||
function isNodeOrNullTuple(arr: [BinaryTreeNodeId | N , N['val']][]): arr is [N , N['val']][] {
|
||||
function isNodeOrNullTuple(arr: [BinaryTreeNodeId | N, N['val']][]): arr is [N, N['val']][] {
|
||||
for (const [idOrNode] of arr) if (idOrNode instanceof BSTNode) return true;
|
||||
return false;
|
||||
}
|
||||
function isBinaryTreeIdOrNullTuple(arr: [BinaryTreeNodeId | N , N['val']][]): arr is [BinaryTreeNodeId , N['val']][] {
|
||||
function isBinaryTreeIdOrNullTuple(arr: [BinaryTreeNodeId | N, N['val']][]): arr is [BinaryTreeNodeId, N['val']][] {
|
||||
for (const [idOrNode] of arr) if (typeof idOrNode === 'number') return true;
|
||||
return false;
|
||||
}
|
||||
let sortedIdsOrNodes: (number | N | null)[] = [], sortedData: (N["val"] | undefined)[] | undefined = [];
|
||||
let sortedIdsOrNodes: (number | N | null)[] = [],
|
||||
sortedData: (N['val'] | undefined)[] | undefined = [];
|
||||
|
||||
if (isNodeOrNullTuple(combinedArr)) {
|
||||
sorted = combinedArr.sort((a, b) => a[0].id - b[0].id);
|
||||
} else if (isBinaryTreeIdOrNullTuple(combinedArr)) {
|
||||
sorted = combinedArr.sort((a, b) => a[0] - b[0]);
|
||||
} else {
|
||||
throw new Error('Invalid input idsOrNodes')
|
||||
throw new Error('Invalid input idsOrNodes');
|
||||
}
|
||||
sortedIdsOrNodes = sorted.map(([idOrNode,]) => idOrNode);
|
||||
sortedData = sorted.map(([,val]) => val);
|
||||
sortedIdsOrNodes = sorted.map(([idOrNode]) => idOrNode);
|
||||
sortedData = sorted.map(([, val]) => val);
|
||||
const recursive = (arr: (BinaryTreeNodeId | null | N)[], data?: N['val'][]) => {
|
||||
if (arr.length === 0) return;
|
||||
|
||||
|
@ -165,7 +179,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
inserted.push(newNode);
|
||||
recursive(arr.slice(0, mid), data?.slice(0, mid));
|
||||
recursive(arr.slice(mid + 1), data?.slice(mid + 1));
|
||||
}
|
||||
};
|
||||
const iterative = () => {
|
||||
const n = sorted.length;
|
||||
const stack: [[number, number]] = [[0, n - 1]];
|
||||
|
@ -182,9 +196,9 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this.loopType === LoopType.RECURSIVE) {
|
||||
recursive(sortedIdsOrNodes, sortedData)
|
||||
recursive(sortedIdsOrNodes, sortedData);
|
||||
} else {
|
||||
iterative();
|
||||
}
|
||||
|
@ -200,7 +214,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
* specifies the property name to use for searching the binary tree nodes. If not provided, it defaults to `'id'`.
|
||||
* @returns The method is returning either a BinaryTreeNodeId or N (generic type) or null.
|
||||
*/
|
||||
override get(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): N | null {
|
||||
override get(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName): N | null {
|
||||
propertyName = propertyName ?? 'id';
|
||||
return this.getNodes(nodeProperty, propertyName, true)[0] ?? null;
|
||||
}
|
||||
|
@ -229,7 +243,11 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
* is set to `true`, the function will return an array with only one node (if
|
||||
* @returns an array of nodes (type N).
|
||||
*/
|
||||
override getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName : BinaryTreeNodePropertyName = 'id', onlyOne ?: boolean): N[] {
|
||||
override getNodes(
|
||||
nodeProperty: BinaryTreeNodeId | N,
|
||||
propertyName: BinaryTreeNodePropertyName = 'id',
|
||||
onlyOne?: boolean
|
||||
): N[] {
|
||||
if (!this.root) return [];
|
||||
const result: N[] = [];
|
||||
|
||||
|
@ -245,7 +263,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(this.root);
|
||||
} else {
|
||||
|
@ -278,7 +296,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
* @returns The function `lesserSum` returns a number, which represents the sum of the values of the nodes in the
|
||||
* binary tree that have a lesser value than the specified `beginNode` based on the `propertyName`.
|
||||
*/
|
||||
lesserSum(beginNode: N | BinaryTreeNodeId | null, propertyName ?: BinaryTreeNodePropertyName): number {
|
||||
lesserSum(beginNode: N | BinaryTreeNodeId | null, propertyName?: BinaryTreeNodePropertyName): number {
|
||||
propertyName = propertyName ?? 'id';
|
||||
if (typeof beginNode === 'number') beginNode = this.get(beginNode, 'id');
|
||||
if (!beginNode) return 0;
|
||||
|
@ -295,7 +313,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
break;
|
||||
}
|
||||
return needSum;
|
||||
}
|
||||
};
|
||||
|
||||
let sum = 0;
|
||||
|
||||
|
@ -326,7 +344,8 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
if (compared === CP.eq) {
|
||||
if (cur.right) sum += this.subTreeSum(cur.right, propertyName);
|
||||
return sum;
|
||||
} else if (compared === CP.lt) { // todo maybe a bug
|
||||
} else if (compared === CP.lt) {
|
||||
// todo maybe a bug
|
||||
if (cur.left) sum += this.subTreeSum(cur.left, propertyName);
|
||||
sum += getSumByPropertyName(cur);
|
||||
if (cur.right) queue.push(cur.right);
|
||||
|
@ -354,7 +373,11 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
* 'id'.
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
allGreaterNodesAdd(node: N | BinaryTreeNodeId | null, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean {
|
||||
allGreaterNodesAdd(
|
||||
node: N | BinaryTreeNodeId | null,
|
||||
delta: number,
|
||||
propertyName?: BinaryTreeNodePropertyName
|
||||
): boolean {
|
||||
propertyName = propertyName ?? 'id';
|
||||
if (typeof node === 'number') node = this.get(node, 'id');
|
||||
if (!node) return false;
|
||||
|
@ -370,7 +393,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
cur.id += delta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this.loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (cur: N) => {
|
||||
const compared = this._compare(cur.id, id);
|
||||
|
@ -409,14 +432,14 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
* AVL Tree: AVL trees are well-suited for scenarios involving frequent searching, insertion, and deletion operations. Through rotation adjustments, AVL trees maintain their balance, ensuring average and worst-case time complexity of O(log n).
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The `perfectlyBalance` function takes a binary tree, performs a depth-first search to sort the nodes, and then
|
||||
* constructs a balanced binary search tree using either a recursive or iterative approach.
|
||||
* @returns The function `perfectlyBalance()` returns a boolean value.
|
||||
*/
|
||||
perfectlyBalance(): boolean {
|
||||
const sorted = this.DFS('in', 'node'), n = sorted.length;
|
||||
const sorted = this.DFS('in', 'node'),
|
||||
n = sorted.length;
|
||||
this.clear();
|
||||
|
||||
if (sorted.length < 1) return false;
|
||||
|
@ -463,14 +486,16 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
if (this.loopType === LoopType.RECURSIVE) {
|
||||
const _height = (cur: N | null | undefined): number => {
|
||||
if (!cur) return 0;
|
||||
const leftHeight = _height(cur.left), rightHeight = _height(cur.right);
|
||||
const leftHeight = _height(cur.left),
|
||||
rightHeight = _height(cur.right);
|
||||
if (Math.abs(leftHeight - rightHeight) > 1) balanced = false;
|
||||
return Math.max(leftHeight, rightHeight) + 1;
|
||||
};
|
||||
_height(this.root);
|
||||
} else {
|
||||
const stack: N[] = [];
|
||||
let node: N | null | undefined = this.root, last: N | null = null;
|
||||
let node: N | null | undefined = this.root,
|
||||
last: N | null = null;
|
||||
const depths: Map<N, number> = new Map();
|
||||
|
||||
while (stack.length > 0 || node) {
|
||||
|
@ -478,7 +503,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
stack.push(node);
|
||||
node = node.left;
|
||||
} else {
|
||||
node = stack[stack.length - 1]
|
||||
node = stack[stack.length - 1];
|
||||
if (!node.right || last === node.right) {
|
||||
node = stack.pop();
|
||||
if (node) {
|
||||
|
@ -489,7 +514,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|||
last = node;
|
||||
node = null;
|
||||
}
|
||||
} else node = node.right
|
||||
} else node = node.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import {BinaryTreeNodeId, RBColor, RBTreeNodeNested, RBTreeOptions} from '../../types';
|
||||
import {IRBTree, IRBTreeNode} from '../../interfaces/rb-tree';
|
||||
import {BST, BSTNode} from './bst';
|
||||
import { BinaryTreeNodeId, RBColor, RBTreeNodeNested, RBTreeOptions } from '../../types';
|
||||
import { IRBTree, IRBTreeNode } from '../../interfaces/rb-tree';
|
||||
import { BST, BSTNode } from './bst';
|
||||
|
||||
|
||||
export class RBTreeNode<T = any, NEIGHBOR extends RBTreeNode<T, NEIGHBOR> = RBTreeNodeNested<T>> extends BSTNode<T, NEIGHBOR> implements IRBTreeNode<T, NEIGHBOR> {
|
||||
export class RBTreeNode<T = any, NEIGHBOR extends RBTreeNode<T, NEIGHBOR> = RBTreeNodeNested<T>>
|
||||
extends BSTNode<T, NEIGHBOR>
|
||||
implements IRBTreeNode<T, NEIGHBOR>
|
||||
{
|
||||
constructor(id: BinaryTreeNodeId, val?: T, color: RBColor = RBColor.RED) {
|
||||
super(id, val);
|
||||
this._color = color;
|
||||
|
@ -19,7 +21,6 @@ export class RBTreeNode<T = any, NEIGHBOR extends RBTreeNode<T, NEIGHBOR> = RBTr
|
|||
this._color = value;
|
||||
}
|
||||
|
||||
|
||||
// private override _parent: RBNode<T> | null;
|
||||
// override set parent(v: RBNode<T> | null) {
|
||||
// this._parent = v;
|
||||
|
@ -97,6 +98,4 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
|
|||
//
|
||||
// return [{deleted: new N(0, 0), needBalanced: null}];
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import type {SegmentTreeNodeVal} from '../../types';
|
||||
import type { SegmentTreeNodeVal } from '../../types';
|
||||
|
||||
export class SegmentTreeNode {
|
||||
constructor(start: number, end: number, sum: number, val?: SegmentTreeNodeVal | null) {
|
||||
|
@ -209,7 +209,6 @@ export class SegmentTree {
|
|||
if (cur.right) {
|
||||
// TODO after no-non-null-assertion not ensure the logic
|
||||
return dfs(cur.right, i, j);
|
||||
|
||||
} else {
|
||||
return NaN;
|
||||
}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class SplayTree {
|
||||
|
||||
}
|
||||
export class SplayTree {}
|
||||
|
|
|
@ -5,13 +5,15 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type {BinaryTreeNodeId, TreeMultisetNodeNested, TreeMultisetOptions} from '../../types';
|
||||
import {BinaryTreeDeletedResult, CP, DFSOrderPattern, FamilyPosition, LoopType} from '../../types';
|
||||
import {ITreeMultiset, ITreeMultisetNode} from '../../interfaces';
|
||||
import {AVLTree, AVLTreeNode} from './avl-tree';
|
||||
|
||||
export class TreeMultisetNode<T = any, NEIGHBOR extends TreeMultisetNode<T, NEIGHBOR> = TreeMultisetNodeNested<T>> extends AVLTreeNode<T, NEIGHBOR> implements ITreeMultisetNode<T, NEIGHBOR> {
|
||||
import type { BinaryTreeNodeId, TreeMultisetNodeNested, TreeMultisetOptions } from '../../types';
|
||||
import { BinaryTreeDeletedResult, CP, DFSOrderPattern, FamilyPosition, LoopType } from '../../types';
|
||||
import { ITreeMultiset, ITreeMultisetNode } from '../../interfaces';
|
||||
import { AVLTree, AVLTreeNode } from './avl-tree';
|
||||
|
||||
export class TreeMultisetNode<T = any, NEIGHBOR extends TreeMultisetNode<T, NEIGHBOR> = TreeMultisetNodeNested<T>>
|
||||
extends AVLTreeNode<T, NEIGHBOR>
|
||||
implements ITreeMultisetNode<T, NEIGHBOR>
|
||||
{
|
||||
/**
|
||||
* The constructor function initializes a BinaryTreeNode object with an id, value, and count.
|
||||
* @param {BinaryTreeNodeId} id - The `id` parameter is of type `BinaryTreeNodeId` and represents the unique identifier
|
||||
|
@ -41,8 +43,10 @@ export class TreeMultisetNode<T = any, NEIGHBOR extends TreeMultisetNode<T, NEIG
|
|||
/**
|
||||
* The only distinction between a TreeMultiset and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.
|
||||
*/
|
||||
export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultisetNode> extends AVLTree<N> implements ITreeMultiset<N> {
|
||||
|
||||
export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultisetNode>
|
||||
extends AVLTree<N>
|
||||
implements ITreeMultiset<N>
|
||||
{
|
||||
/**
|
||||
* The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to
|
||||
* merge duplicated values.
|
||||
|
@ -50,7 +54,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* TreeMultiset.
|
||||
*/
|
||||
constructor(options?: TreeMultisetOptions) {
|
||||
super({...options});
|
||||
super({ ...options });
|
||||
}
|
||||
|
||||
private _count = 0;
|
||||
|
@ -80,7 +84,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* @returns the `destNode` after swapping its values with the `srcNode`.
|
||||
*/
|
||||
override swapLocation(srcNode: N, destNode: N): N {
|
||||
const {id, val, count, height} = destNode;
|
||||
const { id, val, count, height } = destNode;
|
||||
const tempNode = this.createNode(id, val, count);
|
||||
if (tempNode) {
|
||||
tempNode.height = height;
|
||||
|
@ -111,7 +115,8 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
*/
|
||||
override add(idOrNode: BinaryTreeNodeId | N | null, val?: N['val'], count?: number): N | null | undefined {
|
||||
count = count ?? 1;
|
||||
let inserted: N | null | undefined = undefined, newNode: N | null;
|
||||
let inserted: N | null | undefined = undefined,
|
||||
newNode: N | null;
|
||||
if (idOrNode instanceof TreeMultisetNode) {
|
||||
newNode = this.createNode(idOrNode.id, idOrNode.val, idOrNode.count);
|
||||
} else if (idOrNode === null) {
|
||||
|
@ -159,7 +164,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
this._setCount(this.count + newNode.count);
|
||||
|
||||
traversing = false;
|
||||
inserted = (cur.right);
|
||||
inserted = cur.right;
|
||||
} else {
|
||||
//Traverse the left of the current node
|
||||
if (cur.right) cur = cur.right;
|
||||
|
@ -192,12 +197,11 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
parent.left = newNode;
|
||||
if (newNode !== null) {
|
||||
this._setSize(this.size + 1);
|
||||
this._setCount(this.count + newNode.count)
|
||||
this._setCount(this.count + newNode.count);
|
||||
}
|
||||
|
||||
return parent.left;
|
||||
} else if (parent.right === undefined) {
|
||||
|
||||
parent.right = newNode;
|
||||
if (newNode !== null) {
|
||||
this._setSize(this.size + 1);
|
||||
|
@ -222,7 +226,10 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* method. If provided, the `data` array should
|
||||
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
|
||||
*/
|
||||
override addMany(idsOrNodes: (BinaryTreeNodeId | null)[] | (N | null)[], data?: N['val'][]): (N | null | undefined)[] {
|
||||
override addMany(
|
||||
idsOrNodes: (BinaryTreeNodeId | null)[] | (N | null)[],
|
||||
data?: N['val'][]
|
||||
): (N | null | undefined)[] {
|
||||
const inserted: (N | null | undefined)[] = [];
|
||||
|
||||
for (let i = 0; i < idsOrNodes.length; i++) {
|
||||
|
@ -249,7 +256,8 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* @returns The function `perfectlyBalance()` returns a boolean value.
|
||||
*/
|
||||
override perfectlyBalance(): boolean {
|
||||
const sorted = this.DFS('in', 'node'), n = sorted.length;
|
||||
const sorted = this.DFS('in', 'node'),
|
||||
n = sorted.length;
|
||||
if (sorted.length < 1) return false;
|
||||
|
||||
this.clear();
|
||||
|
@ -302,7 +310,8 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
if (!curr) return bstDeletedResult;
|
||||
|
||||
const parent: N | null = curr?.parent ? curr.parent : null;
|
||||
let needBalanced: N | null = null, orgCurrent = curr;
|
||||
let needBalanced: N | null = null,
|
||||
orgCurrent = curr;
|
||||
|
||||
if (curr.count > 1 && !ignoreCount) {
|
||||
curr.count--;
|
||||
|
@ -312,7 +321,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
if (!parent) {
|
||||
if (curr.right !== undefined) this._setRoot(curr.right);
|
||||
} else {
|
||||
const {familyPosition: fp} = curr;
|
||||
const { familyPosition: fp } = curr;
|
||||
if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
|
||||
parent.left = curr.right;
|
||||
} else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
|
||||
|
@ -340,7 +349,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
this._setCount(this.count - orgCurrent.count);
|
||||
}
|
||||
|
||||
bstDeletedResult.push({deleted: orgCurrent, needBalanced});
|
||||
bstDeletedResult.push({ deleted: orgCurrent, needBalanced });
|
||||
|
||||
if (needBalanced) {
|
||||
this._balancePath(needBalanced);
|
||||
|
@ -366,7 +375,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
res[1] += cur.count;
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(subTreeRoot);
|
||||
return res;
|
||||
|
@ -394,7 +403,6 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* @returns the sum of the count values of all nodes in the subtree rooted at `subTreeRoot`.
|
||||
*/
|
||||
subTreeSumCount(subTreeRoot: N | BinaryTreeNodeId | null): number {
|
||||
|
||||
if (typeof subTreeRoot === 'number') subTreeRoot = this.get(subTreeRoot, 'id');
|
||||
|
||||
if (!subTreeRoot) return 0;
|
||||
|
@ -406,7 +414,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
sum += cur.count;
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(subTreeRoot);
|
||||
} else {
|
||||
|
@ -441,7 +449,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
const _addByProperty = (cur: N) => {
|
||||
cur.count += delta;
|
||||
this._setCount(this.count + delta);
|
||||
}
|
||||
};
|
||||
|
||||
if (this.loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (cur: N) => {
|
||||
|
@ -475,7 +483,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* to `true`, the function will return only one node. If `onlyOne`
|
||||
* @returns an array of nodes that match the given nodeProperty.
|
||||
*/
|
||||
getNodesByCount(nodeProperty: BinaryTreeNodeId | N, onlyOne ?: boolean): N[] {
|
||||
getNodesByCount(nodeProperty: BinaryTreeNodeId | N, onlyOne?: boolean): N[] {
|
||||
if (!this.root) return [];
|
||||
const result: N[] = [];
|
||||
|
||||
|
@ -489,7 +497,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
if (!cur.left && !cur.right) return;
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
_traverse(this.root);
|
||||
} else {
|
||||
|
@ -504,7 +512,6 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
|
||||
cur.left && queue.push(cur.left);
|
||||
cur.right && queue.push(cur.right);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +555,6 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
return nodes.map(node => node.count);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The function DFSIterativeCount performs an iterative depth-first search and returns an array of node counts based on
|
||||
* the specified traversal pattern.
|
||||
|
@ -557,13 +563,12 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* @returns The DFSIterativeCount function returns an array of numbers, which represents the count property of each node
|
||||
* in the DFS traversal.
|
||||
*/
|
||||
DFSIterativeCount(pattern ?: 'in' | 'pre' | 'post'): number[] {
|
||||
DFSIterativeCount(pattern?: 'in' | 'pre' | 'post'): number[] {
|
||||
pattern = pattern ?? 'in';
|
||||
const nodes = super.DFSIterative(pattern, 'node');
|
||||
return nodes.map(node => node.count);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The DFSCount function returns an array of counts for each node in a depth-first search traversal.
|
||||
* @param {DFSOrderPattern} [pattern] - The pattern parameter is an optional parameter that specifies the order in which
|
||||
|
@ -575,7 +580,6 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
pattern = pattern ?? 'in';
|
||||
const nodes = super.DFS(pattern, 'node');
|
||||
return nodes.map(node => node.count);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -619,7 +623,8 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
if (compared === CP.eq) {
|
||||
if (cur.right) sum += this.subTreeSumCount(cur.right);
|
||||
return sum;
|
||||
} else if (compared === CP.lt) { // todo maybe a bug
|
||||
} else if (compared === CP.lt) {
|
||||
// todo maybe a bug
|
||||
if (cur.left) sum += this.subTreeSumCount(cur.left);
|
||||
sum += cur.count;
|
||||
if (cur.right) queue.push(cur.right);
|
||||
|
@ -649,7 +654,6 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
const id = node.id;
|
||||
if (!this.root) return false;
|
||||
|
||||
|
||||
if (this.loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (cur: N) => {
|
||||
const compared = this._compare(cur.id, id);
|
||||
|
@ -668,7 +672,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
const cur = queue.shift();
|
||||
if (cur) {
|
||||
const compared = this._compare(cur.id, id);
|
||||
if (compared === CP.gt) cur.count += delta
|
||||
if (compared === CP.gt) cur.count += delta;
|
||||
|
||||
if (cur.left && this._compare(cur.left.id, id) === CP.gt) queue.push(cur.left);
|
||||
if (cur.right && this._compare(cur.right.id, id) === CP.gt) queue.push(cur.right);
|
||||
|
@ -693,5 +697,4 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
protected _setCount(v: number) {
|
||||
this._count = v;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class TwoThreeTree {
|
||||
|
||||
}
|
||||
export class TwoThreeTree {}
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {arrayRemove, uuidV4} from '../../utils';
|
||||
import {PriorityQueue} from '../priority-queue';
|
||||
import type {DijkstraResult, VertexId} from '../../types';
|
||||
import {IAbstractGraph} from '../../interfaces';
|
||||
import { arrayRemove, uuidV4 } from '../../utils';
|
||||
import { PriorityQueue } from '../priority-queue';
|
||||
import type { DijkstraResult, VertexId } from '../../types';
|
||||
import { IAbstractGraph } from '../../interfaces';
|
||||
|
||||
export abstract class AbstractVertex<T = any> {
|
||||
|
||||
/**
|
||||
* The function is a protected constructor that takes an id and an optional value as parameters.
|
||||
* @param {VertexId} id - The `id` parameter is of type `VertexId` and represents the identifier of the vertex. It is
|
||||
|
@ -46,7 +45,6 @@ export abstract class AbstractVertex<T = any> {
|
|||
}
|
||||
|
||||
export abstract class AbstractEdge<T = any> {
|
||||
|
||||
/**
|
||||
* The above function is a protected constructor that initializes the weight, value, and hash code properties of an
|
||||
* object.
|
||||
|
@ -103,7 +101,11 @@ export abstract class AbstractEdge<T = any> {
|
|||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVertex<any>, E extends AbstractEdge<any> = AbstractEdge<any>> implements IAbstractGraph<V, E> {
|
||||
export abstract class AbstractGraph<
|
||||
V extends AbstractVertex<any> = AbstractVertex<any>,
|
||||
E extends AbstractEdge<any> = AbstractEdge<any>
|
||||
> implements IAbstractGraph<V, E>
|
||||
{
|
||||
private _vertices: Map<VertexId, V> = new Map<VertexId, V>();
|
||||
|
||||
get vertices(): Map<VertexId, V> {
|
||||
|
@ -163,14 +165,13 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
return this._vertices.has(this._getVertexId(vertexOrId));
|
||||
}
|
||||
|
||||
addVertex(vertex: V): boolean
|
||||
addVertex(vertex: V): boolean;
|
||||
|
||||
addVertex(id: VertexId, val?: V['val']): boolean
|
||||
addVertex(id: VertexId, val?: V['val']): boolean;
|
||||
|
||||
addVertex(idOrVertex: VertexId | V, val?: V['val']): boolean {
|
||||
if (idOrVertex instanceof AbstractVertex) {
|
||||
return this._addVertexOnly(idOrVertex);
|
||||
|
||||
} else {
|
||||
const newVertex = this.createVertex(idOrVertex, val);
|
||||
return this._addVertexOnly(newVertex);
|
||||
|
@ -216,9 +217,9 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
return !!edge;
|
||||
}
|
||||
|
||||
addEdge(edge: E): boolean
|
||||
addEdge(edge: E): boolean;
|
||||
|
||||
addEdge(src: V | VertexId, dest: V | VertexId, weight?: number, val?: E['val']): boolean
|
||||
addEdge(src: V | VertexId, dest: V | VertexId, weight?: number, val?: E['val']): boolean;
|
||||
|
||||
addEdge(srcOrEdge: V | VertexId | E, dest?: V | VertexId, weight?: number, val?: E['val']): boolean {
|
||||
if (srcOrEdge instanceof AbstractEdge) {
|
||||
|
@ -231,7 +232,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
const newEdge = this.createEdge(srcOrEdge, dest, weight, val);
|
||||
return this._addEdgeOnly(newEdge);
|
||||
} else {
|
||||
throw new Error('dest must be a Vertex or vertex id while srcOrEdge is an Edge')
|
||||
throw new Error('dest must be a Vertex or vertex id while srcOrEdge is an Edge');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,7 +453,12 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
* shortest paths from the source vertex to all other vertices in the graph. If `genPaths
|
||||
* @returns The function `dijkstraWithoutHeap` returns an object of type `DijkstraResult<V>`.
|
||||
*/
|
||||
dijkstraWithoutHeap(src: V | VertexId, dest?: V | VertexId | null, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<V> {
|
||||
dijkstraWithoutHeap(
|
||||
src: V | VertexId,
|
||||
dest?: V | VertexId | null,
|
||||
getMinDist?: boolean,
|
||||
genPaths?: boolean
|
||||
): DijkstraResult<V> {
|
||||
if (getMinDist === undefined) getMinDist = false;
|
||||
if (genPaths === undefined) genPaths = false;
|
||||
|
||||
|
@ -524,7 +530,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
if (genPaths) {
|
||||
getPaths(destVertex);
|
||||
}
|
||||
return {distMap, preMap, seen, paths, minDist, minPath};
|
||||
return { distMap, preMap, seen, paths, minDist, minPath };
|
||||
}
|
||||
const neighbors = this.getNeighbors(cur);
|
||||
for (const neighbor of neighbors) {
|
||||
|
@ -540,25 +546,25 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
preMap.set(neighbor, cur);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getMinDist && distMap.forEach((d, v) => {
|
||||
if (v !== srcVertex) {
|
||||
if (d < minDist) {
|
||||
minDist = d;
|
||||
if (genPaths) minDest = v;
|
||||
getMinDist &&
|
||||
distMap.forEach((d, v) => {
|
||||
if (v !== srcVertex) {
|
||||
if (d < minDist) {
|
||||
minDist = d;
|
||||
if (genPaths) minDest = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
genPaths && getPaths(minDest);
|
||||
|
||||
return {distMap, preMap, seen, paths, minDist, minPath};
|
||||
return { distMap, preMap, seen, paths, minDist, minPath };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -611,8 +617,10 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
if (vertexOrId instanceof AbstractVertex) distMap.set(vertexOrId, Infinity);
|
||||
}
|
||||
|
||||
const heap = new PriorityQueue<{ id: number, val: V }>({comparator: (a, b) => a.id - b.id});
|
||||
heap.add({id: 0, val: srcVertex});
|
||||
const heap = new PriorityQueue<{ id: number; val: V }>({
|
||||
comparator: (a, b) => a.id - b.id
|
||||
});
|
||||
heap.add({ id: 0, val: srcVertex });
|
||||
|
||||
distMap.set(srcVertex, 0);
|
||||
preMap.set(srcVertex, null);
|
||||
|
@ -636,7 +644,6 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
if (vertex[1] === minV) minPath = reversed;
|
||||
paths.push(reversed);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -654,7 +661,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
if (genPaths) {
|
||||
getPaths(destVertex);
|
||||
}
|
||||
return {distMap, preMap, seen, paths, minDist, minPath};
|
||||
return { distMap, preMap, seen, paths, minDist, minPath };
|
||||
}
|
||||
const neighbors = this.getNeighbors(cur);
|
||||
for (const neighbor of neighbors) {
|
||||
|
@ -664,7 +671,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
const distSrcToNeighbor = distMap.get(neighbor);
|
||||
if (distSrcToNeighbor) {
|
||||
if (dist + weight < distSrcToNeighbor) {
|
||||
heap.add({id: dist + weight, val: neighbor});
|
||||
heap.add({ id: dist + weight, val: neighbor });
|
||||
preMap.set(neighbor, cur);
|
||||
distMap.set(neighbor, dist + weight);
|
||||
}
|
||||
|
@ -691,7 +698,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
getPaths(minDest);
|
||||
}
|
||||
|
||||
return {distMap, preMap, seen, paths, minDist, minPath};
|
||||
return { distMap, preMap, seen, paths, minDist, minPath };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -728,7 +735,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
// TODO
|
||||
let hasNegativeCycle: boolean | undefined;
|
||||
if (scanNegativeCycle) hasNegativeCycle = false;
|
||||
if (!srcVertex) return {hasNegativeCycle, distMap, preMap, paths, min, minPath};
|
||||
if (!srcVertex) return { hasNegativeCycle, distMap, preMap, paths, min, minPath };
|
||||
|
||||
const vertices = this._vertices;
|
||||
const numOfVertices = vertices.size;
|
||||
|
@ -800,7 +807,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
}
|
||||
}
|
||||
|
||||
return {hasNegativeCycle, distMap, preMap, paths, min, minPath};
|
||||
return { hasNegativeCycle, distMap, preMap, paths, min, minPath };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -812,7 +819,6 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
* Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* BellmanFord time:O(VE) space:O(V)
|
||||
* one to rest pairs
|
||||
|
@ -842,7 +848,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
|
||||
* path between vertices in the
|
||||
*/
|
||||
floyd(): { costs: number[][], predecessor: (V | null)[][] } {
|
||||
floyd(): { costs: number[][]; predecessor: (V | null)[][] } {
|
||||
const idAndVertices = [...this._vertices];
|
||||
const n = idAndVertices.length;
|
||||
|
||||
|
@ -874,8 +880,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
}
|
||||
}
|
||||
}
|
||||
return {costs, predecessor};
|
||||
|
||||
return { costs, predecessor };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -953,7 +958,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
const curFromMap = dfnMap.get(cur);
|
||||
if (childLow !== undefined && curFromMap !== undefined) {
|
||||
if (needArticulationPoints) {
|
||||
if ((cur === root && childCount >= 2) || ((cur !== root) && (childLow >= curFromMap))) {
|
||||
if ((cur === root && childCount >= 2) || (cur !== root && childLow >= curFromMap)) {
|
||||
// todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {
|
||||
articulationPoints.push(cur);
|
||||
}
|
||||
|
@ -970,7 +975,6 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
dfs(root, null);
|
||||
|
@ -1007,7 +1011,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any> = AbstractVert
|
|||
});
|
||||
}
|
||||
|
||||
return {dfnMap, lowMap, bridges, articulationPoints, SCCs, cycles};
|
||||
return { dfnMap, lowMap, bridges, articulationPoints, SCCs, cycles };
|
||||
}
|
||||
|
||||
protected abstract _addEdgeOnly(edge: E): boolean;
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {arrayRemove} from '../../utils';
|
||||
import {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';
|
||||
import type {TopologicalStatus, VertexId} from '../../types';
|
||||
import {IDirectedGraph} from '../../interfaces';
|
||||
import { arrayRemove } from '../../utils';
|
||||
import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
|
||||
import type { TopologicalStatus, VertexId } from '../../types';
|
||||
import { IDirectedGraph } from '../../interfaces';
|
||||
|
||||
export class DirectedVertex<T = number> extends AbstractVertex<T> {
|
||||
/**
|
||||
|
@ -24,7 +24,6 @@ export class DirectedVertex<T = number> extends AbstractVertex<T> {
|
|||
}
|
||||
|
||||
export class DirectedEdge<T = number> extends AbstractEdge<T> {
|
||||
|
||||
/**
|
||||
* The constructor function initializes the source and destination vertices of an edge, along with an optional weight
|
||||
* and value.
|
||||
|
@ -63,8 +62,10 @@ export class DirectedEdge<T = number> extends AbstractEdge<T> {
|
|||
}
|
||||
}
|
||||
|
||||
export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E extends DirectedEdge<any> = DirectedEdge> extends AbstractGraph<V, E> implements IDirectedGraph<V, E> {
|
||||
|
||||
export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E extends DirectedEdge<any> = DirectedEdge>
|
||||
extends AbstractGraph<V, E>
|
||||
implements IDirectedGraph<V, E>
|
||||
{
|
||||
/**
|
||||
* The constructor function initializes an instance of a class.
|
||||
*/
|
||||
|
@ -107,7 +108,6 @@ export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E ext
|
|||
* This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The function creates a directed edge between two vertices with an optional weight and value.
|
||||
* @param {VertexId} src - The source vertex ID of the edge. It represents the starting point of the edge.
|
||||
|
@ -155,7 +155,6 @@ export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E ext
|
|||
* @returns the removed edge (E) if it exists, or null if either the source or destination vertex does not exist.
|
||||
*/
|
||||
removeEdgeSrcToDest(srcOrId: V | VertexId, destOrId: V | VertexId): E | null {
|
||||
|
||||
const src: V | null = this._getVertex(srcOrId);
|
||||
const dest: V | null = this._getVertex(destOrId);
|
||||
let removed: E | null = null;
|
||||
|
@ -195,7 +194,6 @@ export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E ext
|
|||
if (destInEdges && destInEdges.length > 0) {
|
||||
removed = arrayRemove(destInEdges, (edge: E) => edge.dest === dest.id)[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return removed;
|
||||
|
@ -232,7 +230,7 @@ export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E ext
|
|||
incomingEdgesOf(vertexOrId: V | VertexId): E[] {
|
||||
const target = this._getVertex(vertexOrId);
|
||||
if (target) {
|
||||
return this.inEdgeMap.get(target) || []
|
||||
return this.inEdgeMap.get(target) || [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
@ -368,7 +366,7 @@ export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E ext
|
|||
|
||||
if (hasCycle) return null;
|
||||
|
||||
if (propertyName === 'id') sorted = sorted.map(vertex => vertex instanceof DirectedVertex ? vertex.id : vertex);
|
||||
if (propertyName === 'id') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.id : vertex));
|
||||
return sorted.reverse();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {MapGraphCoordinate, VertexId} from '../../types';
|
||||
import {DirectedEdge, DirectedGraph, DirectedVertex} from './directed-graph';
|
||||
import { MapGraphCoordinate, VertexId } from '../../types';
|
||||
import { DirectedEdge, DirectedGraph, DirectedVertex } from './directed-graph';
|
||||
|
||||
export class MapVertex<T = any> extends DirectedVertex<T> {
|
||||
/**
|
||||
|
@ -57,9 +57,10 @@ export class MapEdge<T = any> extends DirectedEdge<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export class MapGraph<V extends MapVertex<V['val']> = MapVertex, E extends MapEdge = MapEdge> extends DirectedGraph<V, E> {
|
||||
|
||||
export class MapGraph<V extends MapVertex<V['val']> = MapVertex, E extends MapEdge = MapEdge> extends DirectedGraph<
|
||||
V,
|
||||
E
|
||||
> {
|
||||
/**
|
||||
* The constructor function initializes the origin and bottomRight properties of a MapGraphCoordinate object.
|
||||
* @param {MapGraphCoordinate} origin - The `origin` parameter is a `MapGraphCoordinate` object that represents the
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {arrayRemove} from '../../utils';
|
||||
import {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';
|
||||
import type {VertexId} from '../../types';
|
||||
import {IUNDirectedGraph} from '../../interfaces';
|
||||
import { arrayRemove } from '../../utils';
|
||||
import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
|
||||
import type { VertexId } from '../../types';
|
||||
import { IUNDirectedGraph } from '../../interfaces';
|
||||
|
||||
export class UndirectedVertex<T = number> extends AbstractVertex<T> {
|
||||
/**
|
||||
|
@ -50,8 +50,13 @@ export class UndirectedEdge<T = number> extends AbstractEdge<T> {
|
|||
}
|
||||
}
|
||||
|
||||
export class UndirectedGraph<V extends UndirectedVertex<any> = UndirectedVertex, E extends UndirectedEdge<any> = UndirectedEdge> extends AbstractGraph<V, E> implements IUNDirectedGraph<V, E> {
|
||||
|
||||
export class UndirectedGraph<
|
||||
V extends UndirectedVertex<any> = UndirectedVertex,
|
||||
E extends UndirectedEdge<any> = UndirectedEdge
|
||||
>
|
||||
extends AbstractGraph<V, E>
|
||||
implements IUNDirectedGraph<V, E>
|
||||
{
|
||||
/**
|
||||
* The constructor initializes a new Map object to store edges.
|
||||
*/
|
||||
|
@ -124,7 +129,6 @@ export class UndirectedGraph<V extends UndirectedVertex<any> = UndirectedVertex,
|
|||
* @returns the removed edge (E) if it exists, or null if either of the vertices (V) does not exist.
|
||||
*/
|
||||
removeEdgeBetween(v1: V | VertexId, v2: V | VertexId): E | null {
|
||||
|
||||
const vertex1: V | null = this._getVertex(v1);
|
||||
const vertex2: V | null = this._getVertex(v2);
|
||||
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class HashTable {
|
||||
|
||||
}
|
||||
export class HashTable {}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class Pair {
|
||||
|
||||
}
|
||||
export class Pair {}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class TreeMap {
|
||||
|
||||
}
|
||||
export class TreeMap {}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class TreeSet {
|
||||
|
||||
}
|
||||
export class TreeSet {}
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {PriorityQueue} from '../priority-queue';
|
||||
import type {HeapOptions} from '../../types';
|
||||
import { PriorityQueue } from '../priority-queue';
|
||||
import type { HeapOptions } from '../../types';
|
||||
|
||||
export class HeapItem<T = number> {
|
||||
|
||||
/**
|
||||
* The constructor function initializes an instance of a class with a priority and a value.
|
||||
* @param {number} priority - The `priority` parameter is a number that represents the priority of the value. It is
|
||||
|
@ -51,13 +50,13 @@ export abstract class Heap<T = number> {
|
|||
*/
|
||||
protected constructor(options?: HeapOptions<T>) {
|
||||
if (options) {
|
||||
const {priorityExtractor} = options;
|
||||
const { priorityExtractor } = options;
|
||||
if (priorityExtractor !== undefined && typeof priorityExtractor !== 'function') {
|
||||
throw new Error('.constructor expects a valid priority function');
|
||||
}
|
||||
this._priorityExtractor = priorityExtractor || ((el) => +el);
|
||||
this._priorityExtractor = priorityExtractor || (el => +el);
|
||||
} else {
|
||||
this._priorityExtractor = (el) => +el;
|
||||
this._priorityExtractor = el => +el;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,8 +127,8 @@ export abstract class Heap<T = number> {
|
|||
* @returns The `add` method returns the instance of the `Heap` class.
|
||||
* @throws {Error} if priority is not a valid number
|
||||
*/
|
||||
add(priority: number, val?: T,): Heap<T> {
|
||||
val = (val === undefined) ? priority as unknown as T : val;
|
||||
add(priority: number, val?: T): Heap<T> {
|
||||
val = val === undefined ? (priority as unknown as T) : val;
|
||||
this._pq.add(new HeapItem<T>(priority, val));
|
||||
|
||||
return this;
|
||||
|
@ -162,9 +161,11 @@ export abstract class Heap<T = number> {
|
|||
if (node instanceof HeapItem) {
|
||||
return this.pq.getNodes().includes(node);
|
||||
} else {
|
||||
return this.pq.getNodes().findIndex(item => {
|
||||
return item.val === node;
|
||||
}) !== -1;
|
||||
return (
|
||||
this.pq.getNodes().findIndex(item => {
|
||||
return item.val === node;
|
||||
}) !== -1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import {Heap, HeapItem} from './heap';
|
||||
import {PriorityQueue} from '../priority-queue';
|
||||
import type {HeapOptions} from '../../types';
|
||||
import { Heap, HeapItem } from './heap';
|
||||
import { PriorityQueue } from '../priority-queue';
|
||||
import type { HeapOptions } from '../../types';
|
||||
|
||||
/**
|
||||
* @class MaxHeap
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import {Heap, HeapItem} from './heap';
|
||||
import {PriorityQueue} from '../priority-queue';
|
||||
import type {HeapOptions} from '../../types';
|
||||
import { Heap, HeapItem } from './heap';
|
||||
import { PriorityQueue } from '../priority-queue';
|
||||
import type { HeapOptions } from '../../types';
|
||||
|
||||
/**
|
||||
* @class MinHeap
|
||||
|
@ -30,5 +30,3 @@ export class MinHeap<T = number> extends Heap<T> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
export * from './hash';
|
||||
export * from './linked-list';
|
||||
export * from './stack';
|
||||
export * from './queue';
|
||||
export * from './graph';
|
||||
export * from './binary-tree';
|
||||
export * from './tree';
|
||||
export * from './heap';
|
||||
export * from './priority-queue';
|
||||
export * from './matrix';
|
||||
export * from './trie';
|
||||
export * from './hash';
|
||||
export * from './linked-list';
|
||||
export * from './stack';
|
||||
export * from './queue';
|
||||
export * from './graph';
|
||||
export * from './binary-tree';
|
||||
export * from './tree';
|
||||
export * from './heap';
|
||||
export * from './priority-queue';
|
||||
export * from './matrix';
|
||||
export * from './trie';
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
export class DoublyLinkedListNode<T = number> {
|
||||
|
||||
/**
|
||||
* The constructor function initializes the value, next, and previous properties of an object.
|
||||
* @param {T} val - The "val" parameter is the value that will be stored in the node. It can be of any data type, as it
|
||||
|
@ -50,7 +49,6 @@ export class DoublyLinkedListNode<T = number> {
|
|||
}
|
||||
|
||||
export class DoublyLinkedList<T = any> {
|
||||
|
||||
/**
|
||||
* The constructor initializes the linked list with an empty head, tail, and length.
|
||||
*/
|
||||
|
@ -573,4 +571,3 @@ export class DoublyLinkedList<T = any> {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
export class SinglyLinkedListNode<T = number> {
|
||||
|
||||
/**
|
||||
* The constructor function initializes an instance of a class with a given value and sets the next property to null.
|
||||
* @param {T} val - The "val" parameter is of type T, which means it can be any data type. It represents the value that
|
||||
|
@ -39,7 +38,6 @@ export class SinglyLinkedListNode<T = number> {
|
|||
}
|
||||
|
||||
export class SinglyLinkedList<T = any> {
|
||||
|
||||
/**
|
||||
* The constructor initializes the linked list with an empty head, tail, and length.
|
||||
*/
|
||||
|
@ -233,7 +231,8 @@ export class SinglyLinkedList<T = any> {
|
|||
} else {
|
||||
value = valueOrNode;
|
||||
}
|
||||
let current = this.head, prev = null;
|
||||
let current = this.head,
|
||||
prev = null;
|
||||
|
||||
while (current) {
|
||||
if (current.val === value) {
|
||||
|
@ -398,8 +397,8 @@ export class SinglyLinkedList<T = any> {
|
|||
return null;
|
||||
}
|
||||
|
||||
insertBefore(existingValue: T, newValue: T): boolean
|
||||
insertBefore(existingValue: SinglyLinkedListNode<T>, newValue: T): boolean
|
||||
insertBefore(existingValue: T, newValue: T): boolean;
|
||||
insertBefore(existingValue: SinglyLinkedListNode<T>, newValue: T): boolean;
|
||||
|
||||
/**
|
||||
* The `insertBefore` function inserts a new value before an existing value in a singly linked list.
|
||||
|
@ -438,8 +437,8 @@ export class SinglyLinkedList<T = any> {
|
|||
return false;
|
||||
}
|
||||
|
||||
insertAfter(existingValueOrNode: T, newValue: T): boolean
|
||||
insertAfter(existingValueOrNode: SinglyLinkedListNode<T>, newValue: T): boolean
|
||||
insertAfter(existingValueOrNode: T, newValue: T): boolean;
|
||||
insertAfter(existingValueOrNode: SinglyLinkedListNode<T>, newValue: T): boolean;
|
||||
|
||||
/**
|
||||
* The `insertAfter` function inserts a new node with a given value after an existing node in a singly linked list.
|
||||
|
@ -491,8 +490,7 @@ export class SinglyLinkedList<T = any> {
|
|||
return count;
|
||||
}
|
||||
|
||||
|
||||
* [Symbol.iterator]() {
|
||||
*[Symbol.iterator]() {
|
||||
let current = this.head;
|
||||
|
||||
while (current) {
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export class SkipLinkedList {
|
||||
|
||||
}
|
||||
export class SkipLinkedList {}
|
||||
|
|
|
@ -14,8 +14,8 @@ export class MatrixNTI2D<T = number> {
|
|||
* given initial value or 0 if not provided.
|
||||
* @param options - An object containing the following properties:
|
||||
*/
|
||||
constructor(options: { row: number, col: number, initialVal?: T }) {
|
||||
const {row, col, initialVal} = options;
|
||||
constructor(options: { row: number; col: number; initialVal?: T }) {
|
||||
const { row, col, initialVal } = options;
|
||||
this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import Vector2D from './vector2d'
|
||||
import Vector2D from './vector2d';
|
||||
|
||||
export class Matrix2D {
|
||||
private readonly _matrix: number[][];
|
||||
|
@ -18,14 +18,14 @@ export class Matrix2D {
|
|||
*/
|
||||
constructor(value?: number[][] | Vector2D) {
|
||||
if (typeof value === 'undefined') {
|
||||
this._matrix = Matrix2D.identity
|
||||
this._matrix = Matrix2D.identity;
|
||||
} else if (value instanceof Vector2D) {
|
||||
this._matrix = Matrix2D.identity
|
||||
this._matrix[0][0] = value.x
|
||||
this._matrix[1][0] = value.y
|
||||
this._matrix[2][0] = value.w
|
||||
this._matrix = Matrix2D.identity;
|
||||
this._matrix[0][0] = value.x;
|
||||
this._matrix[1][0] = value.y;
|
||||
this._matrix[2][0] = value.w;
|
||||
} else {
|
||||
this._matrix = value
|
||||
this._matrix = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ export class Matrix2D {
|
|||
* @returns An empty 2-dimensional array with 3 empty arrays inside.
|
||||
*/
|
||||
static get empty(): number[][] {
|
||||
return [[], [], []]
|
||||
return [[], [], []];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,8 @@ export class Matrix2D {
|
|||
return [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1]]
|
||||
[0, 0, 1]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +55,7 @@ export class Matrix2D {
|
|||
* array of numbers.
|
||||
*/
|
||||
get m(): number[][] {
|
||||
return this._matrix
|
||||
return this._matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,7 +65,7 @@ export class Matrix2D {
|
|||
* the first column of the matrix.
|
||||
*/
|
||||
get toVector(): Vector2D {
|
||||
return new Vector2D(this._matrix[0][0], this._matrix[1][0])
|
||||
return new Vector2D(this._matrix[0][0], this._matrix[1][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,10 +75,10 @@ export class Matrix2D {
|
|||
* @returns a new instance of the Matrix2D class, which is created using the result array.
|
||||
*/
|
||||
static add(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
|
||||
const result = Matrix2D.empty
|
||||
const result = Matrix2D.empty;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
result[i][j] = matrix1.m[i][j] + matrix2.m[i][j]
|
||||
result[i][j] = matrix1.m[i][j] + matrix2.m[i][j];
|
||||
}
|
||||
}
|
||||
return new Matrix2D(result);
|
||||
|
@ -91,10 +92,10 @@ export class Matrix2D {
|
|||
* @returns a new instance of the Matrix2D class, which is created using the result array.
|
||||
*/
|
||||
static subtract(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
|
||||
const result = Matrix2D.empty
|
||||
const result = Matrix2D.empty;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
result[i][j] = matrix1.m[i][j] - matrix2.m[i][j]
|
||||
result[i][j] = matrix1.m[i][j] - matrix2.m[i][j];
|
||||
}
|
||||
}
|
||||
return new Matrix2D(result);
|
||||
|
@ -107,7 +108,7 @@ export class Matrix2D {
|
|||
* @returns a new instance of the Matrix2D class, created using the result array.
|
||||
*/
|
||||
static multiply(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
|
||||
const result = Matrix2D.empty
|
||||
const result = Matrix2D.empty;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
result[i][j] = 0;
|
||||
|
@ -127,10 +128,10 @@ export class Matrix2D {
|
|||
* @returns a new instance of the Matrix2D class, which is created using the result array.
|
||||
*/
|
||||
static multiplyByValue(matrix: Matrix2D, value: number): Matrix2D {
|
||||
const result = Matrix2D.empty
|
||||
const result = Matrix2D.empty;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
result[i][j] = matrix.m[i][j] * value
|
||||
result[i][j] = matrix.m[i][j] * value;
|
||||
}
|
||||
}
|
||||
return new Matrix2D(result);
|
||||
|
@ -143,7 +144,7 @@ export class Matrix2D {
|
|||
* @returns a Vector2D.
|
||||
*/
|
||||
static multiplyByVector(matrix: Matrix2D, vector: Vector2D): Vector2D {
|
||||
return Matrix2D.multiply(matrix, new Matrix2D(vector)).toVector
|
||||
return Matrix2D.multiply(matrix, new Matrix2D(vector)).toVector;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,15 +156,16 @@ export class Matrix2D {
|
|||
* @returns a Matrix2D object.
|
||||
*/
|
||||
static view(width: number, height: number): Matrix2D {
|
||||
const scaleStep = 1 // Scale every vector * scaleStep
|
||||
const centerX = width / 2
|
||||
const centerY = height / 2
|
||||
const flipX = Math.cos(Math.PI) // rotate 180deg / 3.14radian around X-axis
|
||||
const scaleStep = 1; // Scale every vector * scaleStep
|
||||
const centerX = width / 2;
|
||||
const centerY = height / 2;
|
||||
const flipX = Math.cos(Math.PI); // rotate 180deg / 3.14radian around X-axis
|
||||
|
||||
return new Matrix2D([
|
||||
[scaleStep, 0, centerX],
|
||||
[0, flipX * scaleStep, centerY],
|
||||
[0, 0, 1]])
|
||||
[0, 0, 1]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,7 +175,7 @@ export class Matrix2D {
|
|||
* @returns the result of multiplying a new instance of Matrix2D by the given factor.
|
||||
*/
|
||||
static scale(factor: number) {
|
||||
return Matrix2D.multiplyByValue(new Matrix2D(), factor)
|
||||
return Matrix2D.multiplyByValue(new Matrix2D(), factor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,13 +184,14 @@ export class Matrix2D {
|
|||
* @returns The code is returning a new instance of a Matrix2D object.
|
||||
*/
|
||||
static rotate(radians: number) {
|
||||
const cos = Math.cos(radians)
|
||||
const sin = Math.sin(radians)
|
||||
const cos = Math.cos(radians);
|
||||
const sin = Math.sin(radians);
|
||||
|
||||
return new Matrix2D([
|
||||
[cos, -sin, 0],
|
||||
[sin, cos, 0],
|
||||
[0, 0, 1]])
|
||||
[0, 0, 1]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,8 +204,9 @@ export class Matrix2D {
|
|||
return new Matrix2D([
|
||||
[1, 0, vector.x],
|
||||
[0, 1, vector.y],
|
||||
[0, 0, vector.w]])
|
||||
[0, 0, vector.w]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
export default Matrix2D
|
||||
export default Matrix2D;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type {Direction, NavigatorParams, Turning} from '../../types';
|
||||
import type { Direction, NavigatorParams, Turning } from '../../types';
|
||||
|
||||
export class Character {
|
||||
direction: Direction;
|
||||
|
@ -37,7 +37,7 @@ export class Navigator<T = number> {
|
|||
* in the matrix.
|
||||
* @param - - `matrix`: a 2D array representing the grid or map
|
||||
*/
|
||||
constructor({matrix, turning, onMove, init: {cur, charDir, VISITED}}: NavigatorParams<T>) {
|
||||
constructor({ matrix, turning, onMove, init: { cur, charDir, VISITED } }: NavigatorParams<T>) {
|
||||
this._matrix = matrix;
|
||||
this._cur = cur;
|
||||
this._character = new Character(charDir, turning);
|
||||
|
@ -53,7 +53,7 @@ export class Navigator<T = number> {
|
|||
*/
|
||||
start() {
|
||||
while (this.check(this._character.direction) || this.check(this._character.turn().direction)) {
|
||||
const {direction} = this._character;
|
||||
const { direction } = this._character;
|
||||
if (this.check(direction)) {
|
||||
this.move(direction);
|
||||
} else if (this.check(this._character.turn().direction)) {
|
||||
|
@ -119,4 +119,3 @@ export class Navigator<T = number> {
|
|||
this.onMove && this.onMove(this._cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,15 +10,14 @@ export class Vector2D {
|
|||
public x: number = 0,
|
||||
public y: number = 0,
|
||||
public w: number = 1 // needed for matrix multiplication
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
/**
|
||||
* The function checks if the x and y values of a point are both zero.
|
||||
* @returns A boolean value indicating whether both the x and y properties of the object are equal to 0.
|
||||
*/
|
||||
get isZero(): boolean {
|
||||
return this.x === 0 && this.y === 0
|
||||
return this.x === 0 && this.y === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +25,7 @@ export class Vector2D {
|
|||
* @returns The length of a vector, calculated using the Pythagorean theorem.
|
||||
*/
|
||||
get length(): number {
|
||||
return Math.sqrt((this.x * this.x) + (this.y * this.y))
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,7 +33,7 @@ export class Vector2D {
|
|||
* @returns The method is returning the sum of the squares of the x and y values.
|
||||
*/
|
||||
get lengthSq(): number {
|
||||
return (this.x * this.x) + (this.y * this.y)
|
||||
return this.x * this.x + this.y * this.y;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +42,7 @@ export class Vector2D {
|
|||
* whole number.
|
||||
*/
|
||||
get rounded(): Vector2D {
|
||||
return new Vector2D(Math.round(this.x), Math.round(this.y))
|
||||
return new Vector2D(Math.round(this.x), Math.round(this.y));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +56,7 @@ export class Vector2D {
|
|||
* vectors added together.
|
||||
*/
|
||||
static add(vector1: Vector2D, vector2: Vector2D): Vector2D {
|
||||
return new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y)
|
||||
return new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +71,7 @@ export class Vector2D {
|
|||
* vector2.
|
||||
*/
|
||||
static subtract(vector1: Vector2D, vector2: Vector2D): Vector2D {
|
||||
return new Vector2D(vector1.x - vector2.x, vector1.y - vector2.y)
|
||||
return new Vector2D(vector1.x - vector2.x, vector1.y - vector2.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +84,7 @@ export class Vector2D {
|
|||
* @returns A new Vector2D object with the x and y values subtracted by the given value.
|
||||
*/
|
||||
static subtractValue(vector: Vector2D, value: number): Vector2D {
|
||||
return new Vector2D(vector.x - value, vector.y - value)
|
||||
return new Vector2D(vector.x - value, vector.y - value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,7 +96,7 @@ export class Vector2D {
|
|||
* @returns A new Vector2D object with the x and y values multiplied by the given value.
|
||||
*/
|
||||
static multiply(vector: Vector2D, value: number): Vector2D {
|
||||
return new Vector2D(vector.x * value, vector.y * value)
|
||||
return new Vector2D(vector.x * value, vector.y * value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,7 +108,7 @@ export class Vector2D {
|
|||
* @returns A new instance of the Vector2D class with the x and y values divided by the given value.
|
||||
*/
|
||||
static divide(vector: Vector2D, value: number): Vector2D {
|
||||
return new Vector2D(vector.x / value, vector.y / value)
|
||||
return new Vector2D(vector.x / value, vector.y / value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,7 +119,7 @@ export class Vector2D {
|
|||
* @returns a boolean value, which indicates whether the two input vectors are equal or not.
|
||||
*/
|
||||
static equals(vector1: Vector2D, vector2: Vector2D): boolean {
|
||||
return vector1.x === vector2.x && vector1.y === vector2.y
|
||||
return vector1.x === vector2.x && vector1.y === vector2.y;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,12 +133,12 @@ export class Vector2D {
|
|||
* @returns a boolean value.
|
||||
*/
|
||||
static equalsRounded(vector1: Vector2D, vector2: Vector2D, roundingFactor = 12): boolean {
|
||||
const vector = Vector2D.abs(Vector2D.subtract(vector1, vector2))
|
||||
const vector = Vector2D.abs(Vector2D.subtract(vector1, vector2));
|
||||
if (vector.x < roundingFactor && vector.y < roundingFactor) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,12 +148,13 @@ export class Vector2D {
|
|||
* original vector.
|
||||
*/
|
||||
static normalize(vector: Vector2D): Vector2D {
|
||||
const length = vector.length
|
||||
if (length > 2.220446049250313e-16) { // Epsilon
|
||||
return Vector2D.divide(vector, length)
|
||||
const length = vector.length;
|
||||
if (length > 2.220446049250313e-16) {
|
||||
// Epsilon
|
||||
return Vector2D.divide(vector, length);
|
||||
}
|
||||
|
||||
return vector
|
||||
return vector;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,10 +167,10 @@ export class Vector2D {
|
|||
*/
|
||||
static truncate(vector: Vector2D, max: number): Vector2D {
|
||||
if (vector.length > max) {
|
||||
return Vector2D.multiply(Vector2D.normalize(vector), max)
|
||||
return Vector2D.multiply(Vector2D.normalize(vector), max);
|
||||
}
|
||||
|
||||
return vector
|
||||
return vector;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,7 +179,7 @@ export class Vector2D {
|
|||
* @returns A new Vector2D object is being returned.
|
||||
*/
|
||||
static perp(vector: Vector2D): Vector2D {
|
||||
return new Vector2D(-vector.y, vector.x)
|
||||
return new Vector2D(-vector.y, vector.x);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,7 +189,7 @@ export class Vector2D {
|
|||
* @returns A new Vector2D object with the negated x and y values of the input vector. Returns the vector that is the reverse of this vector
|
||||
*/
|
||||
static reverse(vector: Vector2D): Vector2D {
|
||||
return new Vector2D(-vector.x, -vector.y)
|
||||
return new Vector2D(-vector.x, -vector.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,7 +201,7 @@ export class Vector2D {
|
|||
* input vector.
|
||||
*/
|
||||
static abs(vector: Vector2D): Vector2D {
|
||||
return new Vector2D(Math.abs(vector.x), Math.abs(vector.y))
|
||||
return new Vector2D(Math.abs(vector.x), Math.abs(vector.y));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,7 +212,7 @@ export class Vector2D {
|
|||
* @returns The dot product of the two input vectors.
|
||||
*/
|
||||
static dot(vector1: Vector2D, vector2: Vector2D): number {
|
||||
return (vector1.x * vector2.x) + (vector1.y * vector2.y)
|
||||
return vector1.x * vector2.x + vector1.y * vector2.y;
|
||||
}
|
||||
|
||||
// /**
|
||||
|
@ -242,9 +242,9 @@ export class Vector2D {
|
|||
* @returns The distance between vector1 and vector2.
|
||||
*/
|
||||
static distance(vector1: Vector2D, vector2: Vector2D): number {
|
||||
const ySeparation = vector2.y - vector1.y
|
||||
const xSeparation = vector2.x - vector1.x
|
||||
return Math.sqrt((ySeparation * ySeparation) + (xSeparation * xSeparation))
|
||||
const ySeparation = vector2.y - vector1.y;
|
||||
const xSeparation = vector2.x - vector1.x;
|
||||
return Math.sqrt(ySeparation * ySeparation + xSeparation * xSeparation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -256,9 +256,9 @@ export class Vector2D {
|
|||
* @returns the square of the distance between the two input vectors.
|
||||
*/
|
||||
static distanceSq(vector1: Vector2D, vector2: Vector2D): number {
|
||||
const ySeparation = vector2.y - vector1.y
|
||||
const xSeparation = vector2.x - vector1.x
|
||||
return (ySeparation * ySeparation) + (xSeparation * xSeparation)
|
||||
const ySeparation = vector2.y - vector1.y;
|
||||
const xSeparation = vector2.x - vector1.x;
|
||||
return ySeparation * ySeparation + xSeparation * xSeparation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -272,10 +272,10 @@ export class Vector2D {
|
|||
*/
|
||||
static sign(vector1: Vector2D, vector2: Vector2D): number {
|
||||
if (vector1.y * vector2.x > vector1.x * vector2.y) {
|
||||
return -1
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -286,9 +286,9 @@ export class Vector2D {
|
|||
* @returns the angle between the given vector and the vector (0, -1) in radians.Returns the angle between origin and the given vector in radians
|
||||
*/
|
||||
static angle(vector: Vector2D): number {
|
||||
const origin = new Vector2D(0, -1)
|
||||
const radian = Math.acos(Vector2D.dot(vector, origin) / (vector.length * origin.length))
|
||||
return Vector2D.sign(vector, origin) === 1 ? ((Math.PI * 2) - radian) : radian
|
||||
const origin = new Vector2D(0, -1);
|
||||
const radian = Math.acos(Vector2D.dot(vector, origin) / (vector.length * origin.length));
|
||||
return Vector2D.sign(vector, origin) === 1 ? Math.PI * 2 - radian : radian;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,18 +299,18 @@ export class Vector2D {
|
|||
* @returns a new instance of the Vector2D class with random x and y values.
|
||||
*/
|
||||
static random(maxX: number, maxY: number): Vector2D {
|
||||
const randX = Math.floor(Math.random() * maxX - (maxX / 2))
|
||||
const randY = Math.floor(Math.random() * maxY - (maxY / 2))
|
||||
return new Vector2D(randX, randY)
|
||||
const randX = Math.floor(Math.random() * maxX - maxX / 2);
|
||||
const randY = Math.floor(Math.random() * maxY - maxY / 2);
|
||||
return new Vector2D(randX, randY);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the values of x and y to zero.
|
||||
*/
|
||||
zero(): void {
|
||||
this.x = 0
|
||||
this.y = 0
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
export default Vector2D
|
||||
export default Vector2D;
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {PriorityQueue} from './priority-queue';
|
||||
import type {PriorityQueueOptions, SpecifyOptional} from '../../types';
|
||||
import { PriorityQueue } from './priority-queue';
|
||||
import type { PriorityQueueOptions, SpecifyOptional } from '../../types';
|
||||
|
||||
export class MaxPriorityQueue<T = number> extends PriorityQueue<T> {
|
||||
constructor(options?: Omit<PriorityQueueOptions<number>, 'comparator'>)
|
||||
constructor(options: PriorityQueueOptions<T>)
|
||||
constructor(options?: Omit<PriorityQueueOptions<number>, 'comparator'>);
|
||||
constructor(options: PriorityQueueOptions<T>);
|
||||
|
||||
/**
|
||||
* The constructor initializes a priority queue with an optional comparator function.
|
||||
|
@ -20,15 +20,18 @@ export class MaxPriorityQueue<T = number> extends PriorityQueue<T> {
|
|||
constructor(options?: SpecifyOptional<PriorityQueueOptions<T>, 'comparator'>) {
|
||||
super({
|
||||
...options,
|
||||
comparator: options?.comparator ? options.comparator : (a: T, b: T) => {
|
||||
const aKey = a as unknown as number, bKey = b as unknown as number;
|
||||
return bKey - aKey;
|
||||
}
|
||||
comparator: options?.comparator
|
||||
? options.comparator
|
||||
: (a: T, b: T) => {
|
||||
const aKey = a as unknown as number,
|
||||
bKey = b as unknown as number;
|
||||
return bKey - aKey;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static override heapify<T extends number>(options?: Omit<PriorityQueueOptions<T>, 'comparator'>): MaxPriorityQueue<T>
|
||||
static override heapify<T>(options: PriorityQueueOptions<T>): MaxPriorityQueue<T>
|
||||
static override heapify<T extends number>(options?: Omit<PriorityQueueOptions<T>, 'comparator'>): MaxPriorityQueue<T>;
|
||||
static override heapify<T>(options: PriorityQueueOptions<T>): MaxPriorityQueue<T>;
|
||||
|
||||
/**
|
||||
* The function `heapify` creates a max priority queue from the given options and returns it.
|
||||
|
@ -39,10 +42,13 @@ export class MaxPriorityQueue<T = number> extends PriorityQueue<T> {
|
|||
static override heapify<T>(options: PriorityQueueOptions<T>): MaxPriorityQueue<T> {
|
||||
const maxPQ = new MaxPriorityQueue<T>({
|
||||
...options,
|
||||
comparator: options?.comparator ? options.comparator : (a: T, b: T) => {
|
||||
const aKey = a as unknown as number, bKey = b as unknown as number;
|
||||
return bKey - aKey;
|
||||
}
|
||||
comparator: options?.comparator
|
||||
? options.comparator
|
||||
: (a: T, b: T) => {
|
||||
const aKey = a as unknown as number,
|
||||
bKey = b as unknown as number;
|
||||
return bKey - aKey;
|
||||
}
|
||||
});
|
||||
maxPQ._fix();
|
||||
return maxPQ;
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {PriorityQueue} from './priority-queue';
|
||||
import type {PriorityQueueOptions, SpecifyOptional} from '../../types';
|
||||
import { PriorityQueue } from './priority-queue';
|
||||
import type { PriorityQueueOptions, SpecifyOptional } from '../../types';
|
||||
|
||||
export class MinPriorityQueue<T = number> extends PriorityQueue<T> {
|
||||
constructor(options?: Omit<PriorityQueueOptions<number>, 'comparator'>)
|
||||
constructor(options: PriorityQueueOptions<T>)
|
||||
constructor(options?: Omit<PriorityQueueOptions<number>, 'comparator'>);
|
||||
constructor(options: PriorityQueueOptions<T>);
|
||||
|
||||
/**
|
||||
* The constructor initializes a priority queue with an optional comparator function.
|
||||
|
@ -20,15 +20,18 @@ export class MinPriorityQueue<T = number> extends PriorityQueue<T> {
|
|||
constructor(options?: SpecifyOptional<PriorityQueueOptions<T>, 'comparator'>) {
|
||||
super({
|
||||
...options,
|
||||
comparator: options?.comparator ? options.comparator : (a: T, b: T) => {
|
||||
const aKey = a as unknown as number, bKey = b as unknown as number;
|
||||
return aKey - bKey;
|
||||
}
|
||||
comparator: options?.comparator
|
||||
? options.comparator
|
||||
: (a: T, b: T) => {
|
||||
const aKey = a as unknown as number,
|
||||
bKey = b as unknown as number;
|
||||
return aKey - bKey;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static override heapify<T extends number>(options?: Omit<PriorityQueueOptions<T>, 'comparator'>): MinPriorityQueue<T>
|
||||
static override heapify<T>(options: PriorityQueueOptions<T>): MinPriorityQueue<T>
|
||||
static override heapify<T extends number>(options?: Omit<PriorityQueueOptions<T>, 'comparator'>): MinPriorityQueue<T>;
|
||||
static override heapify<T>(options: PriorityQueueOptions<T>): MinPriorityQueue<T>;
|
||||
|
||||
/**
|
||||
* The function `heapify` creates a new MinPriorityQueue instance and sets the comparator function based on the options
|
||||
|
@ -40,10 +43,13 @@ export class MinPriorityQueue<T = number> extends PriorityQueue<T> {
|
|||
static override heapify<T>(options: PriorityQueueOptions<T>): MinPriorityQueue<T> {
|
||||
const minPQ = new MinPriorityQueue<T>({
|
||||
...options,
|
||||
comparator: options?.comparator ? options.comparator : (a: T, b: T) => {
|
||||
const aKey = a as unknown as number, bKey = b as unknown as number;
|
||||
return aKey - bKey;
|
||||
}
|
||||
comparator: options?.comparator
|
||||
? options.comparator
|
||||
: (a: T, b: T) => {
|
||||
const aKey = a as unknown as number,
|
||||
bKey = b as unknown as number;
|
||||
return aKey - bKey;
|
||||
}
|
||||
});
|
||||
minPQ._fix();
|
||||
return minPQ;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type {PriorityQueueComparator, PriorityQueueDFSOrderPattern, PriorityQueueOptions} from '../../types';
|
||||
import type { PriorityQueueComparator, PriorityQueueDFSOrderPattern, PriorityQueueOptions } from '../../types';
|
||||
|
||||
export class PriorityQueue<T = number> {
|
||||
/**
|
||||
|
@ -14,7 +14,7 @@ export class PriorityQueue<T = number> {
|
|||
* @param options - The `options` parameter is an object that contains the following properties:
|
||||
*/
|
||||
constructor(options: PriorityQueueOptions<T>) {
|
||||
const {nodes, comparator, isFix = true} = options;
|
||||
const { nodes, comparator, isFix = true } = options;
|
||||
this._comparator = comparator;
|
||||
|
||||
if (nodes && Array.isArray(nodes) && nodes.length > 0) {
|
||||
|
@ -55,7 +55,7 @@ export class PriorityQueue<T = number> {
|
|||
* @returns the result of calling the `isValid()` method on a new instance of the `PriorityQueue` class.
|
||||
*/
|
||||
static isPriorityQueueified<T>(options: Omit<PriorityQueueOptions<T>, 'isFix'>) {
|
||||
return new PriorityQueue({...options, isFix: false}).isValid();
|
||||
return new PriorityQueue({ ...options, isFix: false }).isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,7 +151,10 @@ export class PriorityQueue<T = number> {
|
|||
* `comparator` properties as the original instance.
|
||||
*/
|
||||
clone(): PriorityQueue<T> {
|
||||
return new PriorityQueue<T>({nodes: this.nodes, comparator: this._comparator});
|
||||
return new PriorityQueue<T>({
|
||||
nodes: this.nodes,
|
||||
comparator: this._comparator
|
||||
});
|
||||
}
|
||||
|
||||
// --- start additional methods ---
|
||||
|
@ -232,7 +235,8 @@ export class PriorityQueue<T = number> {
|
|||
}
|
||||
|
||||
protected readonly _comparator: PriorityQueueComparator<T> = (a: T, b: T) => {
|
||||
const aKey = a as unknown as number, bKey = b as unknown as number;
|
||||
const aKey = a as unknown as number,
|
||||
bKey = b as unknown as number;
|
||||
return aKey - bKey;
|
||||
};
|
||||
|
||||
|
@ -284,7 +288,7 @@ export class PriorityQueue<T = number> {
|
|||
* @returns the left child of a given parent node in a binary tree.
|
||||
*/
|
||||
protected _getLeft(parent: number): number {
|
||||
return (2 * parent) + 1;
|
||||
return 2 * parent + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -293,7 +297,7 @@ export class PriorityQueue<T = number> {
|
|||
* @returns the right child of a given parent node in a binary tree.
|
||||
*/
|
||||
protected _getRight(parent: number): number {
|
||||
return (2 * parent) + 2;
|
||||
return 2 * parent + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -304,7 +308,8 @@ export class PriorityQueue<T = number> {
|
|||
*/
|
||||
protected _getComparedChild(parent: number) {
|
||||
let min = parent;
|
||||
const left = this._getLeft(parent), right = this._getRight(parent);
|
||||
const left = this._getLeft(parent),
|
||||
right = this._getRight(parent);
|
||||
|
||||
if (left < this.size && this._compare(min, left)) {
|
||||
min = left;
|
||||
|
|
|
@ -5,13 +5,11 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import {DoublyLinkedList} from '../linked-list';
|
||||
import { DoublyLinkedList } from '../linked-list';
|
||||
|
||||
// O(n) time complexity of obtaining the value
|
||||
// O(1) time complexity of adding at the beginning and the end
|
||||
export class Deque<T> extends DoublyLinkedList<T> {
|
||||
|
||||
}
|
||||
export class Deque<T> extends DoublyLinkedList<T> {}
|
||||
|
||||
// O(1) time complexity of obtaining the value
|
||||
// O(n) time complexity of adding at the beginning and the end
|
||||
|
@ -261,7 +259,7 @@ export class ArrayDeque<T> {
|
|||
* @returns The value that is being set at the specified index in the `_nodes` array.
|
||||
*/
|
||||
set(index: number, value: T) {
|
||||
return this._nodes[index] = value;
|
||||
return (this._nodes[index] = value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
* @copyright Tyler Zeng <zrwusa@gmail.com>
|
||||
* @class
|
||||
*/
|
||||
import {SinglyLinkedList} from '../linked-list';
|
||||
import { SinglyLinkedList } from '../linked-list';
|
||||
|
||||
export class LinkedListQueue<T = any> extends SinglyLinkedList<T> {
|
||||
|
||||
/**
|
||||
* The enqueue function adds a value to the end of an array.
|
||||
* @param {T} value - The value parameter represents the value that you want to add to the queue.
|
||||
|
@ -33,7 +32,6 @@ export class LinkedListQueue<T = any> extends SinglyLinkedList<T> {
|
|||
}
|
||||
|
||||
export class Queue<T = any> {
|
||||
|
||||
/**
|
||||
* The constructor initializes an instance of a class with an optional array of elements and sets the offset to 0.
|
||||
* @param {T[]} [elements] - The `elements` parameter is an optional array of elements of type `T`. If provided, it
|
||||
|
@ -185,7 +183,7 @@ export class Queue<T = any> {
|
|||
return new Queue(this.nodes.slice(this.offset));
|
||||
}
|
||||
|
||||
* [Symbol.iterator]() {
|
||||
*[Symbol.iterator]() {
|
||||
for (const item of this.nodes) {
|
||||
yield item;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
export * from './tree';
|
||||
export * from './tree';
|
||||
|
|
|
@ -35,7 +35,7 @@ export class TreeNode<T = any> {
|
|||
this._children = value;
|
||||
}
|
||||
|
||||
addChildren(children: TreeNode<T> | TreeNode<T> []) {
|
||||
addChildren(children: TreeNode<T> | TreeNode<T>[]) {
|
||||
if (!this.children) {
|
||||
this.children = [];
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ export class TreeNode<T = any> {
|
|||
if (level > maxDepth) {
|
||||
maxDepth = level;
|
||||
}
|
||||
const {children} = node;
|
||||
const { children } = node;
|
||||
if (children) {
|
||||
for (let i = 0, len = children.length; i < len; i++) {
|
||||
bfs(children[i], level + 1);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
export class TrieNode {
|
||||
|
||||
constructor(v: string) {
|
||||
this._val = v;
|
||||
this._isEnd = false;
|
||||
|
@ -42,7 +41,6 @@ export class TrieNode {
|
|||
set isEnd(v: boolean) {
|
||||
this._isEnd = v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class Trie {
|
||||
|
@ -115,7 +113,7 @@ export class Trie {
|
|||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
dfs(this.root, 0);
|
||||
return isDeleted;
|
||||
|
@ -166,7 +164,7 @@ export class Trie {
|
|||
if (cur.isEnd) return;
|
||||
if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);
|
||||
else return;
|
||||
}
|
||||
};
|
||||
dfs(this._root);
|
||||
return commonPre === input;
|
||||
}
|
||||
|
@ -184,7 +182,7 @@ export class Trie {
|
|||
if (cur.isEnd) return;
|
||||
if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);
|
||||
else return;
|
||||
}
|
||||
};
|
||||
dfs(this._root);
|
||||
return commonPre;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export * from './data-structures';
|
||||
export * from './utils';
|
||||
export * from './interfaces';
|
||||
export * from './types';
|
||||
export * from './types';
|
||||
|
|
|
@ -9,107 +9,106 @@ import {
|
|||
LoopType,
|
||||
NodeOrPropertyName
|
||||
} from '../types';
|
||||
import {AbstractBinaryTreeNode} from '../data-structures';
|
||||
import { AbstractBinaryTreeNode } from '../data-structures';
|
||||
|
||||
export interface IAbstractBinaryTreeNode<T, NEIGHBOR extends IAbstractBinaryTreeNode<T, NEIGHBOR>> {
|
||||
get id(): BinaryTreeNodeId;
|
||||
|
||||
get id(): BinaryTreeNodeId
|
||||
set id(v: BinaryTreeNodeId);
|
||||
|
||||
set id(v: BinaryTreeNodeId)
|
||||
get val(): T | undefined;
|
||||
|
||||
get val(): T | undefined
|
||||
set val(v: T | undefined);
|
||||
|
||||
set val(v: T | undefined)
|
||||
get left(): NEIGHBOR | null | undefined;
|
||||
|
||||
get left(): NEIGHBOR | null | undefined
|
||||
set left(v: NEIGHBOR | null | undefined);
|
||||
|
||||
set left(v: NEIGHBOR | null | undefined)
|
||||
get right(): NEIGHBOR | null | undefined;
|
||||
|
||||
get right(): NEIGHBOR | null | undefined
|
||||
set right(v: NEIGHBOR | null | undefined);
|
||||
|
||||
set right(v: NEIGHBOR | null | undefined)
|
||||
get parent(): NEIGHBOR | null | undefined;
|
||||
|
||||
get parent(): NEIGHBOR | null | undefined
|
||||
set parent(v: NEIGHBOR | null | undefined);
|
||||
|
||||
set parent(v: NEIGHBOR | null | undefined)
|
||||
get familyPosition(): FamilyPosition;
|
||||
|
||||
get familyPosition(): FamilyPosition
|
||||
get height(): number;
|
||||
|
||||
get height(): number
|
||||
|
||||
set height(v: number)
|
||||
set height(v: number);
|
||||
}
|
||||
|
||||
export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'], N>> {
|
||||
createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N | null
|
||||
createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N | null;
|
||||
|
||||
get loopType(): LoopType
|
||||
get loopType(): LoopType;
|
||||
|
||||
get visitedId(): BinaryTreeNodeId[]
|
||||
get visitedId(): BinaryTreeNodeId[];
|
||||
|
||||
get visitedVal(): Array<N['val']>
|
||||
get visitedVal(): Array<N['val']>;
|
||||
|
||||
get visitedNode(): N[]
|
||||
get visitedNode(): N[];
|
||||
|
||||
get visitedLeftSum(): number[]
|
||||
get visitedLeftSum(): number[];
|
||||
|
||||
get root(): N | null
|
||||
get root(): N | null;
|
||||
|
||||
get size(): number
|
||||
get size(): number;
|
||||
|
||||
swapLocation(srcNode: N, destNode: N): N
|
||||
swapLocation(srcNode: N, destNode: N): N;
|
||||
|
||||
clear(): void
|
||||
clear(): void;
|
||||
|
||||
isEmpty(): boolean
|
||||
isEmpty(): boolean;
|
||||
|
||||
add(id: BinaryTreeNodeId | N, val?: N['val']): N | null | undefined
|
||||
add(id: BinaryTreeNodeId | N, val?: N['val']): N | null | undefined;
|
||||
|
||||
addMany(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N['val'][]): (N | null | undefined)[]
|
||||
addMany(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N['val'][]): (N | null | undefined)[];
|
||||
|
||||
fill(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N[] | Array<N['val']>): boolean
|
||||
fill(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N[] | Array<N['val']>): boolean;
|
||||
|
||||
remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeletedResult<N>[]
|
||||
remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeletedResult<N>[];
|
||||
|
||||
getDepth(node: N): number
|
||||
getDepth(node: N): number;
|
||||
|
||||
getHeight(beginRoot?: N | null): number
|
||||
getHeight(beginRoot?: N | null): number;
|
||||
|
||||
getMinHeight(beginRoot?: N | null): number
|
||||
getMinHeight(beginRoot?: N | null): number;
|
||||
|
||||
isPerfectlyBalanced(beginRoot?: N | null): boolean
|
||||
isPerfectlyBalanced(beginRoot?: N | null): boolean;
|
||||
|
||||
getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean): N[]
|
||||
getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName, onlyOne?: boolean): N[];
|
||||
|
||||
has(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): boolean
|
||||
has(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName): boolean;
|
||||
|
||||
get(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): N | null
|
||||
get(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName): N | null;
|
||||
|
||||
getPathToRoot(node: N): N[]
|
||||
getPathToRoot(node: N): N[];
|
||||
|
||||
getLeftMost(): N | null;
|
||||
|
||||
getLeftMost(node: N): N;
|
||||
|
||||
getLeftMost(node?: N | null): N | null
|
||||
getLeftMost(node?: N | null): N | null;
|
||||
|
||||
getRightMost(): N | null;
|
||||
|
||||
getRightMost(node: N): N;
|
||||
|
||||
getRightMost(node?: N | null): N | null
|
||||
getRightMost(node?: N | null): N | null;
|
||||
|
||||
isSubtreeBST(node: N | null): boolean
|
||||
isSubtreeBST(node: N | null): boolean;
|
||||
|
||||
isBST(): boolean
|
||||
isBST(): boolean;
|
||||
|
||||
getSubTreeSize(subTreeRoot: N | null | undefined): number
|
||||
getSubTreeSize(subTreeRoot: N | null | undefined): number;
|
||||
|
||||
// --- start additional methods ---
|
||||
|
||||
subTreeSum(subTreeRoot: N, propertyName ?: BinaryTreeNodePropertyName): number
|
||||
subTreeSum(subTreeRoot: N, propertyName?: BinaryTreeNodePropertyName): number;
|
||||
|
||||
subTreeAdd(subTreeRoot: N, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean
|
||||
subTreeAdd(subTreeRoot: N, delta: number, propertyName?: BinaryTreeNodePropertyName): boolean;
|
||||
|
||||
BFS(): BinaryTreeNodeId[];
|
||||
|
||||
|
@ -121,7 +120,7 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
BFS(nodeOrPropertyName: 'count'): number[];
|
||||
|
||||
BFS(nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>
|
||||
BFS(nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>;
|
||||
|
||||
DFS(): BinaryTreeNodeId[];
|
||||
|
||||
|
@ -133,7 +132,7 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
|
||||
|
||||
DFS(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>
|
||||
DFS(pattern?: 'in' | 'pre' | 'post', nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>;
|
||||
|
||||
DFSIterative(): BinaryTreeNodeId[];
|
||||
|
||||
|
@ -145,7 +144,10 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
|
||||
|
||||
DFSIterative(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>
|
||||
DFSIterative(
|
||||
pattern?: 'in' | 'pre' | 'post',
|
||||
nodeOrPropertyName?: NodeOrPropertyName
|
||||
): AbstractBinaryTreeNodeProperties<N>;
|
||||
|
||||
levelIterative(node: N | null): BinaryTreeNodeId[];
|
||||
|
||||
|
@ -157,7 +159,7 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
levelIterative(node: N | null, nodeOrPropertyName?: 'count'): number[];
|
||||
|
||||
levelIterative(node: N | null, nodeOrPropertyName ?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>
|
||||
levelIterative(node: N | null, nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>;
|
||||
|
||||
listLevels(node: N | null): BinaryTreeNodeId[][];
|
||||
|
||||
|
@ -169,9 +171,9 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
listLevels(node: N | null, nodeOrPropertyName?: 'count'): number[][];
|
||||
|
||||
listLevels(node: N | null, nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperty<N>[][]
|
||||
listLevels(node: N | null, nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperty<N>[][];
|
||||
|
||||
getPredecessor(node: N): N
|
||||
getPredecessor(node: N): N;
|
||||
|
||||
morris(): BinaryTreeNodeId[];
|
||||
|
||||
|
@ -183,8 +185,7 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
|
||||
|
||||
morris(pattern?: 'in' | 'pre' | 'post', nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>
|
||||
|
||||
morris(pattern?: 'in' | 'pre' | 'post', nodeOrPropertyName?: NodeOrPropertyName): AbstractBinaryTreeNodeProperties<N>;
|
||||
|
||||
// --- end additional methods ---
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {VertexId} from '../types';
|
||||
import { VertexId } from '../types';
|
||||
|
||||
export interface IAbstractGraph<V, E> {
|
||||
|
||||
hasVertex(vertexOrId: V | VertexId): boolean;
|
||||
|
||||
addVertex(id: VertexId, val?: V): boolean;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import {AVLTreeNode} from '../data-structures';
|
||||
import {IBST, IBSTNode} from './bst';
|
||||
import {BinaryTreeDeletedResult, BinaryTreeNodeId} from '../types';
|
||||
import { AVLTreeNode } from '../data-structures';
|
||||
import { IBST, IBSTNode } from './bst';
|
||||
import { BinaryTreeDeletedResult, BinaryTreeNodeId } from '../types';
|
||||
|
||||
export type IAVLTreeNode<T, NEIGHBOR extends IAVLTreeNode<T, NEIGHBOR>> = IBSTNode<T, NEIGHBOR>
|
||||
export type IAVLTreeNode<T, NEIGHBOR extends IAVLTreeNode<T, NEIGHBOR>> = IBSTNode<T, NEIGHBOR>;
|
||||
|
||||
export interface IAVLTree<N extends AVLTreeNode<N['val'], N>> extends IBST<N> {
|
||||
add(id: BinaryTreeNodeId, val?: N['val'] | null): N | null | undefined;
|
||||
|
||||
add(id: BinaryTreeNodeId, val?: N['val'] | null): N | null | undefined
|
||||
|
||||
remove(id: BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): BinaryTreeDeletedResult<N>[]
|
||||
remove(id: BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): BinaryTreeDeletedResult<N>[];
|
||||
|
||||
// _balanceFactor(node: N): number
|
||||
//
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {BinaryTreeNode} from '../data-structures';
|
||||
import {IAbstractBinaryTree, IAbstractBinaryTreeNode} from './abstract-binary-tree';
|
||||
import { BinaryTreeNode } from '../data-structures';
|
||||
import { IAbstractBinaryTree, IAbstractBinaryTreeNode } from './abstract-binary-tree';
|
||||
|
||||
export type IBinaryTreeNode<T, NEIGHBOR extends IBinaryTreeNode<T, NEIGHBOR>> = IAbstractBinaryTreeNode<T, NEIGHBOR>
|
||||
export type IBinaryTreeNode<T, NEIGHBOR extends IBinaryTreeNode<T, NEIGHBOR>> = IAbstractBinaryTreeNode<T, NEIGHBOR>;
|
||||
|
||||
export type IBinaryTree<N extends BinaryTreeNode<N['val'], N>> = IAbstractBinaryTree<N>
|
||||
export type IBinaryTree<N extends BinaryTreeNode<N['val'], N>> = IAbstractBinaryTree<N>;
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
import {BSTNode} from '../data-structures';
|
||||
import {IBinaryTree, IBinaryTreeNode} from './binary-tree';
|
||||
import {BinaryTreeDeletedResult, BinaryTreeNodeId, BinaryTreeNodePropertyName} from '../types';
|
||||
import { BSTNode } from '../data-structures';
|
||||
import { IBinaryTree, IBinaryTreeNode } from './binary-tree';
|
||||
import { BinaryTreeDeletedResult, BinaryTreeNodeId, BinaryTreeNodePropertyName } from '../types';
|
||||
|
||||
export type IBSTNode<T, NEIGHBOR extends IBSTNode<T, NEIGHBOR>> = IBinaryTreeNode<T, NEIGHBOR>
|
||||
export type IBSTNode<T, NEIGHBOR extends IBSTNode<T, NEIGHBOR>> = IBinaryTreeNode<T, NEIGHBOR>;
|
||||
|
||||
export interface IBST<N extends BSTNode<N['val'], N>> extends IBinaryTree<N> {
|
||||
createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N
|
||||
createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N;
|
||||
|
||||
add(id: BinaryTreeNodeId, val?: N['val'] | null, count?: number): N | null | undefined
|
||||
add(id: BinaryTreeNodeId, val?: N['val'] | null, count?: number): N | null | undefined;
|
||||
|
||||
get(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): N | null
|
||||
get(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName): N | null;
|
||||
|
||||
lastKey(): BinaryTreeNodeId
|
||||
lastKey(): BinaryTreeNodeId;
|
||||
|
||||
remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeletedResult<N>[]
|
||||
remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeletedResult<N>[];
|
||||
|
||||
getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean): N[]
|
||||
getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName?: BinaryTreeNodePropertyName, onlyOne?: boolean): N[];
|
||||
|
||||
// --- start additional functions
|
||||
|
||||
lesserSum(id: BinaryTreeNodeId, propertyName ?: BinaryTreeNodePropertyName): number
|
||||
lesserSum(id: BinaryTreeNodeId, propertyName?: BinaryTreeNodePropertyName): number;
|
||||
|
||||
allGreaterNodesAdd(node: N, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean
|
||||
allGreaterNodesAdd(node: N, delta: number, propertyName?: BinaryTreeNodePropertyName): boolean;
|
||||
|
||||
perfectlyBalance(): boolean
|
||||
perfectlyBalance(): boolean;
|
||||
|
||||
isAVLBalanced(): boolean
|
||||
isAVLBalanced(): boolean;
|
||||
|
||||
// --- end additional functions
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {VertexId} from '../types';
|
||||
import {IAbstractGraph} from './abstract-graph';
|
||||
import { VertexId } from '../types';
|
||||
import { IAbstractGraph } from './abstract-graph';
|
||||
|
||||
export interface IDirectedGraph<V, E> extends IAbstractGraph<V, E> {
|
||||
incomingEdgesOf(vertex: V): E[];
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -12,4 +12,4 @@ export * from './rb-tree';
|
|||
export * from './segment-tree';
|
||||
export * from './singly-linked-list';
|
||||
export * from './tree-multiset';
|
||||
export * from './undirected-graph';
|
||||
export * from './undirected-graph';
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import {RBTreeNode} from '../data-structures';
|
||||
import {IBST, IBSTNode} from './bst';
|
||||
import {BinaryTreeNodeId} from '../types';
|
||||
import { RBTreeNode } from '../data-structures';
|
||||
import { IBST, IBSTNode } from './bst';
|
||||
import { BinaryTreeNodeId } from '../types';
|
||||
|
||||
export type IRBTreeNode<T, NEIGHBOR extends IRBTreeNode<T, NEIGHBOR>> = IBSTNode<T, NEIGHBOR>
|
||||
export type IRBTreeNode<T, NEIGHBOR extends IRBTreeNode<T, NEIGHBOR>> = IBSTNode<T, NEIGHBOR>;
|
||||
|
||||
export interface IRBTree<N extends RBTreeNode<N['val'], N>> extends IBST<N> {
|
||||
|
||||
createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N
|
||||
createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {TreeMultisetNode} from '../data-structures';
|
||||
import {IBSTNode} from './bst';
|
||||
import {IAVLTree} from './avl-tree';
|
||||
import { TreeMultisetNode } from '../data-structures';
|
||||
import { IBSTNode } from './bst';
|
||||
import { IAVLTree } from './avl-tree';
|
||||
|
||||
export type ITreeMultisetNode<T, NEIGHBOR extends ITreeMultisetNode<T, NEIGHBOR>> = IBSTNode<T, NEIGHBOR>
|
||||
export type ITreeMultisetNode<T, NEIGHBOR extends ITreeMultisetNode<T, NEIGHBOR>> = IBSTNode<T, NEIGHBOR>;
|
||||
|
||||
export type ITreeMultiset<N extends TreeMultisetNode<N['val'], N>> = IAVLTree<N>
|
||||
export type ITreeMultiset<N extends TreeMultisetNode<N['val'], N>> = IAVLTree<N>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {VertexId} from '../types';
|
||||
import {IAbstractGraph} from './abstract-graph';
|
||||
import { VertexId } from '../types';
|
||||
import { IAbstractGraph } from './abstract-graph';
|
||||
|
||||
export interface IUNDirectedGraph<V, E> extends IAbstractGraph<V, E> {
|
||||
removeEdgeBetween(v1: V | VertexId, v2: V | VertexId): E | null;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {AbstractBinaryTreeNode} from '../../data-structures/binary-tree';
|
||||
import {AbstractBinaryTreeNode} from '../../data-structures';
|
||||
|
||||
/**
|
||||
* Enum representing different loop types.
|
||||
|
@ -6,7 +6,11 @@ import {AbstractBinaryTreeNode} from '../../data-structures/binary-tree';
|
|||
* - `iterative`: Indicates the iterative loop type (with loops that use iterations).
|
||||
* - `recursive`: Indicates the recursive loop type (with loops that call themselves).
|
||||
*/
|
||||
export enum LoopType { ITERATIVE = 'ITERATIVE', RECURSIVE = 'RECURSIVE'}
|
||||
|
||||
export enum LoopType {
|
||||
ITERATIVE = 'ITERATIVE',
|
||||
RECURSIVE = 'RECURSIVE'
|
||||
}
|
||||
|
||||
/* This enumeration defines the position of a node within a family tree composed of three associated nodes, where 'root' represents the root node of the family tree, 'left' represents the left child node, and 'right' represents the right child node. */
|
||||
export enum FamilyPosition {
|
||||
|
@ -20,21 +24,27 @@ export enum FamilyPosition {
|
|||
}
|
||||
|
||||
export type BinaryTreeNodePropertyName = 'id' | 'val';
|
||||
|
||||
export type NodeOrPropertyName = 'node' | BinaryTreeNodePropertyName;
|
||||
|
||||
export type DFSOrderPattern = 'in' | 'pre' | 'post';
|
||||
|
||||
export type BinaryTreeNodeId = number;
|
||||
export type BinaryTreeDeletedResult<N> = { deleted: N | null | undefined, needBalanced: N | null };
|
||||
|
||||
export type BinaryTreeDeletedResult<N> = { deleted: N | null | undefined; needBalanced: N | null };
|
||||
|
||||
export type AbstractBinaryTreeNodeProperty<N extends AbstractBinaryTreeNode<N['val'], N>> =
|
||||
N['val']
|
||||
| N['val']
|
||||
| N
|
||||
| number
|
||||
| BinaryTreeNodeId;
|
||||
|
||||
export type AbstractBinaryTreeNodeProperties<N extends AbstractBinaryTreeNode<N['val'], N>> = AbstractBinaryTreeNodeProperty<N>[];
|
||||
|
||||
export type AbstractBinaryTreeNodeNested<T> = AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
export type AbstractBinaryTreeNodeProperties<N extends AbstractBinaryTreeNode<N['val'], N>> =
|
||||
AbstractBinaryTreeNodeProperty<N>[];
|
||||
|
||||
export type AbstractBinaryTreeNodeNested<T> = AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, AbstractBinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
|
||||
|
||||
export type AbstractBinaryTreeOptions = {
|
||||
loopType?: LoopType,
|
||||
}
|
||||
loopType?: LoopType
|
||||
};
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
export type VertexId = string | number;
|
||||
export type EdgeId = string;
|
||||
export type DijkstraResult<V> =
|
||||
{ distMap: Map<V, number>, distPaths?: Map<V, V[]>, preMap: Map<V, V | null>, seen: Set<V>, paths: V[][], minDist: number, minPath: V[] }
|
||||
| null;
|
||||
export type DijkstraResult<V> = {
|
||||
distMap: Map<V, number>;
|
||||
distPaths?: Map<V, V[]>;
|
||||
preMap: Map<V, V | null>;
|
||||
seen: Set<V>;
|
||||
paths: V[][];
|
||||
minDist: number;
|
||||
minPath: V[];
|
||||
} | null;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {AVLTreeNode} from '../../data-structures/binary-tree';
|
||||
import {AVLTreeNode} from '../../data-structures';
|
||||
import {BSTOptions} from './bst';
|
||||
|
||||
export type AVLTreeNodeNested<T> = AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
export type AVLTreeOptions = BSTOptions & {};
|
||||
export type AVLTreeOptions = BSTOptions & {};
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import {BinaryTreeNode} from '../../data-structures/binary-tree';
|
||||
import {AbstractBinaryTreeOptions} from './abstract-binary-tree';
|
||||
|
||||
|
||||
// export type BinaryTreeDeleted<N> = { deleted: N | null | undefined, needBalanced: N | null };
|
||||
// export type ResultByProperty<N extends BinaryTreeNode<N['val'], N>> = N['val'] | N | number | BinaryTreeNodeId;
|
||||
// export type ResultsByProperty<N extends BinaryTreeNode<N['val'], N>> = ResultByProperty<N>[];
|
||||
export type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
export type BinaryTreeOptions = AbstractBinaryTreeOptions & {}
|
||||
export type BinaryTreeOptions = AbstractBinaryTreeOptions & {}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {BinaryTreeNodeId} from './abstract-binary-tree';
|
|||
|
||||
export type BSTComparator = (a: BinaryTreeNodeId, b: BinaryTreeNodeId) => number;
|
||||
|
||||
// prettier-ignore
|
||||
export type BSTNodeNested<T> = BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
export type BSTOptions = BinaryTreeOptions & {
|
||||
comparator?: BSTComparator,
|
||||
|
|
|
@ -4,5 +4,5 @@ export type TopologicalStatus = 0 | 1 | 2;
|
|||
export enum TopologicalProperty {
|
||||
VAL = 'VAL',
|
||||
NODE = 'NODE',
|
||||
ID = 'ID',
|
||||
ID = 'ID'
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -2,4 +2,4 @@ export type HeapOptions<T> = {
|
|||
priorityExtractor?: (element: T) => number;
|
||||
// TODO there is an idea that support chaining which is for conveniently using the data structure
|
||||
// isChaining? : boolean
|
||||
}
|
||||
};
|
||||
|
|
|
@ -12,4 +12,4 @@ export * from './priority-queue';
|
|||
export * from './heap';
|
||||
export * from './singly-linked-list';
|
||||
export * from './doubly-linked-list';
|
||||
export * from './navigator';
|
||||
export * from './navigator';
|
||||
|
|
|
@ -1 +1 @@
|
|||
export type MapGraphCoordinate = [number, number];
|
||||
export type MapGraphCoordinate = [number, number];
|
||||
|
|
|
@ -2,12 +2,12 @@ export type Direction = 'up' | 'right' | 'down' | 'left';
|
|||
export type Turning = { [key in Direction]: Direction };
|
||||
|
||||
export type NavigatorParams<T> = {
|
||||
matrix: T[][],
|
||||
turning: Turning,
|
||||
onMove: (cur: [number, number]) => void
|
||||
matrix: T[][];
|
||||
turning: Turning;
|
||||
onMove: (cur: [number, number]) => void;
|
||||
init: {
|
||||
cur: [number, number],
|
||||
charDir: Direction,
|
||||
VISITED: T,
|
||||
}
|
||||
}
|
||||
cur: [number, number];
|
||||
charDir: Direction;
|
||||
VISITED: T;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,6 +4,6 @@ export type PriorityQueueOptions<T> = {
|
|||
nodes?: T[];
|
||||
isFix?: boolean;
|
||||
comparator: PriorityQueueComparator<T>;
|
||||
}
|
||||
};
|
||||
|
||||
export type PriorityQueueDFSOrderPattern = 'pre' | 'in' | 'post';
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1 +1 @@
|
|||
export {}
|
||||
export {};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export * from './data-structures';
|
||||
export * from './helpers';
|
||||
export * from './utils';
|
||||
export * from './utils';
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
export * from './utils';
|
||||
export * from './validate-type';
|
||||
export * from './validate-type';
|
||||
|
|
|
@ -1,25 +1,35 @@
|
|||
export type KeyValueObject = { [key: string]: any };
|
||||
|
||||
export type KeyValueObjectWithId = { [key: string]: any, id: string | number | symbol };
|
||||
export type KeyValueObjectWithId = { [key: string]: any; id: string | number | symbol };
|
||||
|
||||
export type NonNumberNonObjectButDefined = string | boolean | symbol | null;
|
||||
|
||||
export type ObjectWithoutId = Omit<KeyValueObject, 'id'>;
|
||||
|
||||
export type ObjectWithNonNumberId = {
|
||||
[key: string]: any,
|
||||
[key: string]: any;
|
||||
id: string | boolean | symbol | null | object | undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export type ObjectWithNumberId = {
|
||||
[key: string]: any,
|
||||
[key: string]: any;
|
||||
id: number;
|
||||
}
|
||||
};
|
||||
|
||||
export type RestrictValById =
|
||||
NonNumberNonObjectButDefined
|
||||
| NonNumberNonObjectButDefined
|
||||
| ObjectWithoutId
|
||||
| ObjectWithNonNumberId
|
||||
| ObjectWithNumberId;
|
||||
|
||||
export type DummyAny = string | number | boolean | null | undefined | object | symbol | void | ((...args: []) => any) | never;
|
||||
export type DummyAny =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| undefined
|
||||
| object
|
||||
| symbol
|
||||
| void
|
||||
| ((...args: []) => any)
|
||||
| never;
|
||||
|
|
|
@ -5,17 +5,19 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type {Thunk, ToThunkFn, TrlAsyncFn, TrlFn} from '../types';
|
||||
import type { Thunk, ToThunkFn, TrlAsyncFn, TrlFn } from '../types';
|
||||
|
||||
export const uuidV4 = function () {
|
||||
return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {
|
||||
const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
const r = (Math.random() * 16) | 0,
|
||||
v = c == 'x' ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
};
|
||||
|
||||
export const arrayRemove = function <T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean): T[] {
|
||||
let i = -1, len = array ? array.length : 0;
|
||||
let i = -1,
|
||||
len = array ? array.length : 0;
|
||||
const result = [];
|
||||
|
||||
while (++i < len) {
|
||||
|
@ -30,49 +32,48 @@ export const arrayRemove = function <T>(array: T[], predicate: (item: T, index:
|
|||
return result;
|
||||
};
|
||||
|
||||
|
||||
export const THUNK_SYMBOL = Symbol('thunk')
|
||||
export const THUNK_SYMBOL = Symbol('thunk');
|
||||
|
||||
export const isThunk = (fnOrValue: any) => {
|
||||
return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL
|
||||
}
|
||||
return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL;
|
||||
};
|
||||
|
||||
export const toThunk = (fn: ToThunkFn): Thunk => {
|
||||
const thunk = () => fn()
|
||||
thunk.__THUNK__ = THUNK_SYMBOL
|
||||
return thunk
|
||||
}
|
||||
const thunk = () => fn();
|
||||
thunk.__THUNK__ = THUNK_SYMBOL;
|
||||
return thunk;
|
||||
};
|
||||
|
||||
export const trampoline = (fn: TrlFn) => {
|
||||
const cont = (...args: [...Parameters<TrlFn>]) => toThunk(() => fn(...args))
|
||||
const cont = (...args: [...Parameters<TrlFn>]) => toThunk(() => fn(...args));
|
||||
|
||||
return Object.assign(
|
||||
(...args: [...Parameters<TrlFn>]) => {
|
||||
let result = fn(...args)
|
||||
let result = fn(...args);
|
||||
|
||||
while (isThunk(result) && typeof result === 'function') {
|
||||
result = result()
|
||||
result = result();
|
||||
}
|
||||
|
||||
return result
|
||||
return result;
|
||||
},
|
||||
{cont}
|
||||
)
|
||||
}
|
||||
{ cont }
|
||||
);
|
||||
};
|
||||
|
||||
export const trampolineAsync = (fn: TrlAsyncFn) => {
|
||||
const cont = (...args: [...Parameters<TrlAsyncFn>]) => toThunk(() => fn(...args))
|
||||
const cont = (...args: [...Parameters<TrlAsyncFn>]) => toThunk(() => fn(...args));
|
||||
|
||||
return Object.assign(
|
||||
async (...args: [...Parameters<TrlAsyncFn>]) => {
|
||||
let result = await fn(...args)
|
||||
let result = await fn(...args);
|
||||
|
||||
while (isThunk(result) && typeof result === 'function') {
|
||||
result = await result()
|
||||
result = await result();
|
||||
}
|
||||
|
||||
return result
|
||||
return result;
|
||||
},
|
||||
{cont}
|
||||
)
|
||||
}
|
||||
{ cont }
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"module": "CommonJS",
|
||||
// "target": "CommonJS",
|
||||
"target": "ES6",
|
||||
"lib": [
|
||||
"esnext",
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = [
|
|||
target: 'web',
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
path: path.resolve(__dirname, 'lib'),
|
||||
library: 'dataStructureTyped',
|
||||
libraryTarget: 'window',
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue