diff --git a/.idea/modules.xml b/.idea/modules.xml
index eaebbb7..be7ecd0 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 50cf0c9..4116668 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,25 +1,32 @@
{
"name": "data-structure-typed",
- "version": "0.8.6",
- "lockfileVersion": 2,
+ "version": "0.9.16",
+ "lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
- "version": "0.8.6",
+ "version": "0.9.16",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.21"
},
"devDependencies": {
- "@types/lodash": "^4.14.178",
+ "@types/lodash": "^4.14.197",
+ "@types/node": "^20.4.9",
"typescript": "^4.6.2"
}
},
"node_modules/@types/lodash": {
- "version": "4.14.195",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz",
- "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==",
+ "version": "4.14.197",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz",
+ "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.4.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz",
+ "integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==",
"dev": true
},
"node_modules/lodash": {
@@ -40,24 +47,5 @@
"node": ">=4.2.0"
}
}
- },
- "dependencies": {
- "@types/lodash": {
- "version": "4.14.195",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz",
- "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==",
- "dev": true
- },
- "lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
- },
- "typescript": {
- "version": "4.9.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
- "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
- "dev": true
- }
}
}
diff --git a/package.json b/package.json
index 0a5a2dc..8fc6e62 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,10 @@
{
"name": "data-structure-typed",
- "version": "0.8.18",
+ "version": "0.9.16",
"description": "Hash (CoordinateSet, CoordinateMap) Heap (MaxHeap, MinHeap) Binary Tree (AVL Tree, Binary Indexed Tree, Binary Search Tree, Segment Tree, Tree Multiset) Graph (Directed Graph, Undirected Graph) Linked List (Singly Linked List, Doubly Linked List) Matrix Priority Queue (Max Priority Queue, Min Priority Queue) Queue (Queue, Dequeue) Stack Trie",
"main": "dist/index.js",
"scripts": {
+ "build": "rm -rf dist && npx tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@@ -11,51 +12,27 @@
"url": "git+https://github.com/zrwusa/data-structure-typed.git"
},
"keywords": [
+ "Binary Tree",
+ "AVL Tree",
+ "Binary Search Tree (BST)",
+ "Tree Multiset",
+ "Segment Tree",
+ "Binary Indexed Tree",
+ "Graph",
+ "Directed Graph",
+ "Undirected Graph",
+ "Singly Linked List",
"Hash",
"CoordinateSet",
"CoordinateMap",
"Heap",
- "MaxHeap",
- "MinHeap",
- "Binary",
- "Tree",
- "AVL",
- "Tree",
- "Binary",
- "Indexed",
- "Tree",
- "Binary",
- "Search",
- "Tree",
- "Segment",
- "Tree",
- "Tree",
- "Multiset",
- "Graph",
- "Directed",
- "Graph",
- "Undirected",
- "Graph",
- "Linked",
- "List",
- "Singly",
- "Linked",
- "List",
- "Doubly",
- "Linked",
- "List",
- "Matrix",
- "Priority",
+ "Doubly Linked List",
+ "Priority Queue",
+ "Max Priority Queue",
+ "Min Priority Queue",
"Queue",
- "Max",
- "Priority",
- "Queue",
- "Min",
- "Priority",
- "Queue",
- "Queue",
- "Queue",
- "Dequeue",
+ "ObjectDeque",
+ "ArrayDeque",
"Stack",
"Trie"
],
@@ -67,7 +44,8 @@
"homepage": "https://github.com/zrwusa/data-structure-typed#readme",
"types": "dist/index.d.ts",
"devDependencies": {
- "@types/lodash": "^4.14.178",
+ "@types/lodash": "^4.14.197",
+ "@types/node": "^20.4.9",
"typescript": "^4.6.2"
},
"dependencies": {
diff --git a/src/assets/complexities-diff.jpg b/src/assets/complexities-diff.jpg
deleted file mode 100644
index 53248a9..0000000
Binary files a/src/assets/complexities-diff.jpg and /dev/null differ
diff --git a/src/assets/data-structure-complexities.jpg b/src/assets/data-structure-complexities.jpg
deleted file mode 100644
index 6f3f284..0000000
Binary files a/src/assets/data-structure-complexities.jpg and /dev/null differ
diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts
index 3de4505..4089aea 100644
--- a/src/data-structures/binary-tree/avl-tree.ts
+++ b/src/data-structures/binary-tree/avl-tree.ts
@@ -1,10 +1,5 @@
import {BST, BSTNode} from './bst';
-import {BinaryTreeNodeId} from './binary-tree';
-
-export interface AVLTreeDeleted {
- deleted: AVLTreeNode | null;
- needBalanced: AVLTreeNode | null;
-}
+import type {AVLTreeDeleted, BinaryTreeNodeId} from '../types';
export class AVLTreeNode extends BSTNode {
override clone(): AVLTreeNode {
diff --git a/src/data-structures/binary-tree/binary-indexed-tree.ts b/src/data-structures/binary-tree/binary-indexed-tree.ts
index 01d85e7..51fe68c 100644
--- a/src/data-structures/binary-tree/binary-indexed-tree.ts
+++ b/src/data-structures/binary-tree/binary-indexed-tree.ts
@@ -5,6 +5,10 @@ export class BinaryIndexedTree {
this._sumTree = new Array(n + 1).fill(0);
}
+ static lowBit(x: number) {
+ return x & (-x);
+ }
+
update(i: number, delta: number) {
while (i < this._sumTree.length) {
this._sumTree[i] += delta;
@@ -26,8 +30,4 @@ export class BinaryIndexedTree {
throw 'Index out of bounds';
return this.getPrefixSum(end) - this.getPrefixSum(start);
}
-
- static lowBit(x: number) {
- return x & (-x);
- }
}
diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts
index 4d53a2b..f99d9ec 100644
--- a/src/data-structures/binary-tree/binary-tree.ts
+++ b/src/data-structures/binary-tree/binary-tree.ts
@@ -1,25 +1,27 @@
-import {ThunkOrValue, trampoline} from '../trampoline';
-
-export type BinaryTreeNodePropertyName = 'id' | 'val' | 'count';
-export type NodeOrPropertyName = 'node' | BinaryTreeNodePropertyName;
-export type DFSOrderPattern = 'in' | 'pre' | 'post';
-export type BinaryTreeNodeId = number;
-export type BinaryTreeDeleted = { deleted: BinaryTreeNode | null | undefined, needBalanced: BinaryTreeNode | null };
-export type ResultByProperty = T | BinaryTreeNode | number | BinaryTreeNodeId;
-export type ResultsByProperty = ResultByProperty[];
-
-export interface BinaryTreeNodeObj {
- id: BinaryTreeNodeId;
- val: T;
- count?: number;
-}
+import {trampoline} from '../trampoline';
+import type {
+ BinaryTreeDeleted,
+ BinaryTreeNodeId,
+ BinaryTreeNodePropertyName,
+ DFSOrderPattern,
+ NodeOrPropertyName,
+ ResultByProperty,
+ ResultsByProperty
+} from '../types';
export enum FamilyPosition {root, left, right}
export enum LoopType { iterative = 1, recursive = 2}
export class BinaryTreeNode {
+ constructor(id: BinaryTreeNodeId, val: T, count?: number) {
+ this._id = id;
+ this._val = val;
+ this._count = count ?? 1;
+ }
+
protected _id: BinaryTreeNodeId;
+
get id(): BinaryTreeNodeId {
return this._id;
}
@@ -29,6 +31,7 @@ export class BinaryTreeNode {
}
protected _val: T;
+
get val(): T {
return this._val;
}
@@ -38,6 +41,7 @@ export class BinaryTreeNode {
}
protected _left?: BinaryTreeNode | null;
+
get left(): BinaryTreeNode | null | undefined {
return this._left;
}
@@ -51,6 +55,7 @@ export class BinaryTreeNode {
}
protected _right?: BinaryTreeNode | null;
+
get right(): BinaryTreeNode | null | undefined {
return this._right;
}
@@ -63,7 +68,8 @@ export class BinaryTreeNode {
this._right = v;
}
- protected _parent: BinaryTreeNode | null | undefined = undefined;
+ protected _parent: BinaryTreeNode | null | undefined;
+
get parent(): BinaryTreeNode | null | undefined {
return this._parent;
}
@@ -73,6 +79,7 @@ export class BinaryTreeNode {
}
protected _familyPosition: FamilyPosition = FamilyPosition.root;
+
get familyPosition(): FamilyPosition {
return this._familyPosition;
}
@@ -82,6 +89,7 @@ export class BinaryTreeNode {
}
protected _count = 1;
+
get count(): number {
return this._count;
}
@@ -100,12 +108,6 @@ export class BinaryTreeNode {
this._height = v;
}
- constructor(id: BinaryTreeNodeId, val: T, count?: number) {
- this._id = id;
- this._val = val;
- this._count = count ?? 1;
- }
-
swapLocation(swapNode: BinaryTreeNode): BinaryTreeNode {
const {val, count, height} = swapNode;
const tempNode = new BinaryTreeNode(swapNode.id, val);
@@ -131,55 +133,15 @@ export class BinaryTreeNode {
}
export class BinaryTree {
- protected _root: BinaryTreeNode | null = null;
- public get root(): BinaryTreeNode | null {
- return this._root;
- }
-
- protected set root(v: BinaryTreeNode | null) {
- if (v) {
- v.parent = null;
- v.familyPosition = FamilyPosition.root;
- }
- this._root = v;
- }
-
- protected _size = 0;
- get size(): number {
- return this._size;
- }
-
- protected set size(v: number) {
- this._size = v;
- }
-
- protected _count = 0;
- get count(): number {
- return this._count;
- }
-
- protected set count(v: number) {
- this._count = v;
- }
-
- private readonly _autoIncrementId: boolean = false;
- private _maxId: number = -1;
- private readonly _isDuplicatedVal: boolean = false;
-
protected _loopType: LoopType = LoopType.iterative;
protected _visitedId: BinaryTreeNodeId[] = [];
protected _visitedVal: Array = [];
protected _visitedNode: BinaryTreeNode[] = [];
protected _visitedCount: number[] = [];
protected _visitedLeftSum: number[] = [];
-
- protected _resetResults() {
- this._visitedId = [];
- this._visitedVal = [];
- this._visitedNode = [];
- this._visitedCount = [];
- this._visitedLeftSum = [];
- }
+ private readonly _autoIncrementId: boolean = false;
+ private _maxId: number = -1;
+ private readonly _isDuplicatedVal: boolean = false;
constructor(options?: {
loopType?: LoopType,
@@ -198,6 +160,44 @@ export class BinaryTree {
}
}
+ protected _root: BinaryTreeNode | null = null;
+
+ protected get root(): BinaryTreeNode | null {
+ return this._root;
+ }
+
+ protected set root(v: BinaryTreeNode | null) {
+ if (v) {
+ v.parent = null;
+ v.familyPosition = FamilyPosition.root;
+ }
+ this._root = v;
+ }
+
+ protected _size = 0;
+
+ protected get size(): number {
+ return this._size;
+ }
+
+ protected set size(v: number) {
+ this._size = v;
+ }
+
+ protected _count = 0;
+
+ protected get count(): number {
+ return this._count;
+ }
+
+ protected set count(v: number) {
+ this._count = v;
+ }
+
+ getCount(): number {
+ return this._count;
+ }
+
createNode(id: BinaryTreeNodeId, val: T | null, count?: number): BinaryTreeNode | null {
return val !== null ? new BinaryTreeNode(id, val, count) : null;
}
@@ -393,8 +393,8 @@ export class BinaryTree {
return _getMaxHeight(beginRoot);
} else {
const stack: BinaryTreeNode[] = [];
- let node: BinaryTreeNode | null | undefined = beginRoot, last: BinaryTreeNode | null = null,
- depths: Map, number> = new Map();
+ let node: BinaryTreeNode | null | undefined = beginRoot, last: BinaryTreeNode | null = null;
+ const depths: Map, number> = new Map();
while (stack.length > 0 || node) {
if (node) {
@@ -405,8 +405,8 @@ export class BinaryTree {
if (!node.right || last === node.right) {
node = stack.pop();
if (node) {
- let leftHeight = node.left ? depths.get(node.left) ?? -1 : -1;
- let rightHeight = node.right ? depths.get(node.right) ?? -1 : -1;
+ const leftHeight = node.left ? depths.get(node.left) ?? -1 : -1;
+ const rightHeight = node.right ? depths.get(node.right) ?? -1 : -1;
depths.set(node, 1 + Math.max(leftHeight, rightHeight));
last = node;
node = null;
@@ -435,8 +435,8 @@ export class BinaryTree {
return _getMinHeight(beginRoot);
} else {
const stack: BinaryTreeNode[] = [];
- let node: BinaryTreeNode | null | undefined = beginRoot, last: BinaryTreeNode | null = null,
- depths: Map, number> = new Map();
+ let node: BinaryTreeNode | null | undefined = beginRoot, last: BinaryTreeNode | null = null;
+ const depths: Map, number> = new Map();
while (stack.length > 0 || node) {
if (node) {
@@ -447,8 +447,8 @@ export class BinaryTree {
if (!node.right || last === node.right) {
node = stack.pop();
if (node) {
- let leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
- let rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
+ const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
+ const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
last = node;
node = null;
@@ -514,76 +514,14 @@ export class BinaryTree {
return result;
}
- protected _pushByPropertyNameStopOrNot(cur: BinaryTreeNode, result: (BinaryTreeNode | null | undefined)[], nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
- switch (propertyName) {
- case 'id':
- if (cur.id === nodeProperty) {
- result.push(cur);
- return !!onlyOne;
- }
- break;
- case 'count':
- if (cur.count === nodeProperty) {
- result.push(cur);
- return !!onlyOne;
- }
- break;
- case 'val':
- if (cur.val === nodeProperty) {
- result.push(cur);
- return !!onlyOne;
- }
- break;
- default:
- if (cur.id === nodeProperty) {
- result.push(cur);
- return !!onlyOne;
- }
- break;
- }
- }
-
- protected _accumulatedByPropertyName(node: BinaryTreeNode, nodeOrPropertyName ?: NodeOrPropertyName) {
- nodeOrPropertyName = nodeOrPropertyName ?? 'id';
-
- switch (nodeOrPropertyName) {
- case 'id':
- this._visitedId.push(node.id);
- break;
- case 'val':
- this._visitedVal.push(node.val);
- break;
- case 'node':
- this._visitedNode.push(node);
- break;
- case 'count':
- this._visitedCount.push(node.count);
- break;
- default:
- this._visitedId.push(node.id);
- break;
- }
- }
-
- protected _getResultByPropertyName(nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty {
- nodeOrPropertyName = nodeOrPropertyName ?? 'id';
-
- switch (nodeOrPropertyName) {
- case 'id':
- return this._visitedId;
- case 'val':
- return this._visitedVal;
- case 'node':
- return this._visitedNode;
- case 'count':
- return this._visitedCount;
- default:
- return this._visitedId;
- }
+ getRoot(): BinaryTreeNode | null {
+ return this.root;
}
getLeftMost(): BinaryTreeNode | null;
+
getLeftMost(node: BinaryTreeNode): BinaryTreeNode;
+
getLeftMost(node?: BinaryTreeNode | null): BinaryTreeNode | null {
node = node ?? this.root;
if (!node) return node;
@@ -598,7 +536,7 @@ export class BinaryTree {
return _traverse(node);
} else {
// Indirect implementation of iteration using tail recursion optimization
- const _traverse = trampoline((cur: BinaryTreeNode): ThunkOrValue | null> => {
+ const _traverse = trampoline((cur: BinaryTreeNode) => {
if (!cur.left) return cur;
return _traverse.cont(cur.left);
});
@@ -608,7 +546,9 @@ export class BinaryTree {
}
getRightMost(): BinaryTreeNode | null;
+
getRightMost(node: BinaryTreeNode): BinaryTreeNode;
+
getRightMost(node?: BinaryTreeNode | null): BinaryTreeNode | null {
node = node ?? this.root;
if (!node) return node;
@@ -622,7 +562,7 @@ export class BinaryTree {
return _traverse(node);
} else {
// Indirect implementation of iteration using tail recursion optimization
- const _traverse = trampoline((cur: BinaryTreeNode): ThunkOrValue | null> => {
+ const _traverse = trampoline((cur: BinaryTreeNode) => {
if (!cur.right) return cur;
return _traverse.cont(cur.right);
});
@@ -653,7 +593,7 @@ export class BinaryTree {
curr = curr.left;
}
curr = stack.pop()!;
- if (prev >= curr.id) return false;
+ if (!(curr) || prev >= curr.id) return false;
prev = curr.id;
curr = curr.right;
}
@@ -779,10 +719,15 @@ export class BinaryTree {
}
BFS(): BinaryTreeNodeId[];
+
BFS(nodeOrPropertyName: 'id'): BinaryTreeNodeId[];
+
BFS(nodeOrPropertyName: 'val'): T[];
+
BFS(nodeOrPropertyName: 'node'): BinaryTreeNode[];
+
BFS(nodeOrPropertyName: 'count'): number[];
+
BFS(nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty {
nodeOrPropertyName = nodeOrPropertyName ?? 'id';
this._resetResults();
@@ -801,10 +746,15 @@ export class BinaryTree {
}
DFS(): BinaryTreeNodeId[];
+
DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
+
DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): T[];
+
DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'node'): BinaryTreeNode[];
+
DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
+
DFS(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty {
pattern = pattern ?? 'in';
nodeOrPropertyName = nodeOrPropertyName ?? 'id';
@@ -834,9 +784,13 @@ export class BinaryTree {
}
DFSIterative(): BinaryTreeNodeId[];
+
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
+
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): T[];
+
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'node'): BinaryTreeNode[];
+
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
/**
@@ -889,10 +843,15 @@ export class BinaryTree {
}
levelIterative(node: BinaryTreeNode | null): BinaryTreeNodeId[];
+
levelIterative(node: BinaryTreeNode | null, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
+
levelIterative(node: BinaryTreeNode | null, nodeOrPropertyName?: 'val'): T[];
+
levelIterative(node: BinaryTreeNode | null, nodeOrPropertyName?: 'node'): BinaryTreeNode[];
+
levelIterative(node: BinaryTreeNode | null, nodeOrPropertyName?: 'count'): number[];
+
levelIterative(node: BinaryTreeNode | null, nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty {
nodeOrPropertyName = nodeOrPropertyName || 'id';
node = node || this.root;
@@ -918,10 +877,15 @@ export class BinaryTree {
}
listLevels(node: BinaryTreeNode | null): BinaryTreeNodeId[][];
+
listLevels(node: BinaryTreeNode | null, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[][];
+
listLevels(node: BinaryTreeNode | null, nodeOrPropertyName?: 'val'): T[][];
+
listLevels(node: BinaryTreeNode | null, nodeOrPropertyName?: 'node'): BinaryTreeNode[][];
+
listLevels(node: BinaryTreeNode | null, nodeOrPropertyName?: 'count'): number[][];
+
listLevels(node: BinaryTreeNode | null, nodeOrPropertyName?: NodeOrPropertyName): ResultByProperty[][] {
nodeOrPropertyName = nodeOrPropertyName || 'id';
node = node || this.root;
@@ -977,9 +941,11 @@ export class BinaryTree {
getPredecessor(node: BinaryTreeNode): BinaryTreeNode {
if (node.left) {
- let predecessor: BinaryTreeNode | null = node.left;
- while (predecessor.right && predecessor.right !== node) {
- predecessor = predecessor.right;
+ let predecessor: BinaryTreeNode | null | undefined = node.left;
+ while (!(predecessor) || predecessor.right && predecessor.right !== node) {
+ if (predecessor) {
+ predecessor = predecessor.right;
+ }
}
return predecessor;
} else {
@@ -988,10 +954,15 @@ export class BinaryTree {
}
morris(): BinaryTreeNodeId[];
+
morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
+
morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): T[];
+
morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'node'): BinaryTreeNode[];
+
morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
+
/**
* The time complexity of Morris traversal is O(n), it's may slower than others
* The space complexity Morris traversal is O(1) because no using stack
@@ -1084,5 +1055,81 @@ export class BinaryTree {
return this._getResultByPropertyName(nodeOrPropertyName);
}
+ protected _resetResults() {
+ this._visitedId = [];
+ this._visitedVal = [];
+ this._visitedNode = [];
+ this._visitedCount = [];
+ this._visitedLeftSum = [];
+ }
+
+ protected _pushByPropertyNameStopOrNot(cur: BinaryTreeNode, result: (BinaryTreeNode | null | undefined)[], nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
+ switch (propertyName) {
+ case 'id':
+ if (cur.id === nodeProperty) {
+ result.push(cur);
+ return !!onlyOne;
+ }
+ break;
+ case 'count':
+ if (cur.count === nodeProperty) {
+ result.push(cur);
+ return !!onlyOne;
+ }
+ break;
+ case 'val':
+ if (cur.val === nodeProperty) {
+ result.push(cur);
+ return !!onlyOne;
+ }
+ break;
+ default:
+ if (cur.id === nodeProperty) {
+ result.push(cur);
+ return !!onlyOne;
+ }
+ break;
+ }
+ }
+
+ protected _accumulatedByPropertyName(node: BinaryTreeNode, nodeOrPropertyName ?: NodeOrPropertyName) {
+ nodeOrPropertyName = nodeOrPropertyName ?? 'id';
+
+ switch (nodeOrPropertyName) {
+ case 'id':
+ this._visitedId.push(node.id);
+ break;
+ case 'val':
+ this._visitedVal.push(node.val);
+ break;
+ case 'node':
+ this._visitedNode.push(node);
+ break;
+ case 'count':
+ this._visitedCount.push(node.count);
+ break;
+ default:
+ this._visitedId.push(node.id);
+ break;
+ }
+ }
+
+ protected _getResultByPropertyName(nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty {
+ nodeOrPropertyName = nodeOrPropertyName ?? 'id';
+
+ switch (nodeOrPropertyName) {
+ case 'id':
+ return this._visitedId;
+ case 'val':
+ return this._visitedVal;
+ case 'node':
+ return this._visitedNode;
+ case 'count':
+ return this._visitedCount;
+ default:
+ return this._visitedId;
+ }
+ }
+
// --- end additional methods ---
}
\ No newline at end of file
diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts
index 2393f23..1b136d1 100644
--- a/src/data-structures/binary-tree/bst.ts
+++ b/src/data-structures/binary-tree/bst.ts
@@ -1,14 +1,5 @@
-import {
- BinaryTree,
- BinaryTreeNode,
- BinaryTreeNodeId,
- BinaryTreeNodePropertyName,
- FamilyPosition,
- LoopType,
-} from './binary-tree';
-
-export type BSTComparator = (a: BinaryTreeNodeId, b: BinaryTreeNodeId) => number;
-export type BSTDeletedResult = { deleted: BSTNode | null, needBalanced: BSTNode | null };
+import type {BinaryTreeNodeId, BinaryTreeNodePropertyName, BSTComparator, BSTDeletedResult} from '../types';
+import {BinaryTree, BinaryTreeNode, FamilyPosition, LoopType,} from './binary-tree';
export enum CP {lt = -1, eq = 0, gt = 1}
@@ -19,15 +10,6 @@ export class BSTNode extends BinaryTreeNode {
}
export class BST extends BinaryTree {
- protected _comparator: BSTComparator = (a, b) => a - b;
-
- protected _compare(a: BinaryTreeNodeId, b: BinaryTreeNodeId): CP {
- const compared = this._comparator(a, b);
- if (compared > 0) return CP.gt;
- else if (compared < 0) return CP.lt;
- else return CP.eq;
- }
-
constructor(options?: {
comparator?: BSTComparator,
loopType?: LoopType
@@ -373,8 +355,8 @@ export class BST extends BinaryTree {
_height(this.root);
} else {
const stack: BSTNode[] = [];
- let node: BSTNode | null | undefined = this.root, last: BSTNode | null = null,
- depths: Map, number> = new Map();
+ let node: BSTNode | null | undefined = this.root, last: BSTNode | null = null;
+ const depths: Map, number> = new Map();
while (stack.length > 0 || node) {
if (node) {
@@ -385,8 +367,8 @@ export class BST extends BinaryTree {
if (!node.right || last === node.right) {
node = stack.pop();
if (node) {
- let left = node.left ? depths.get(node.left) ?? -1 : -1;
- let right = node.right ? depths.get(node.right) ?? -1 : -1;
+ const left = node.left ? depths.get(node.left) ?? -1 : -1;
+ const right = node.right ? depths.get(node.right) ?? -1 : -1;
if (Math.abs(left - right) > 1) return false;
depths.set(node, 1 + Math.max(left, right));
last = node;
@@ -400,5 +382,14 @@ export class BST extends BinaryTree {
return balanced;
}
+ protected _comparator: BSTComparator = (a, b) => a - b;
+
+ protected _compare(a: BinaryTreeNodeId, b: BinaryTreeNodeId): CP {
+ const compared = this._comparator(a, b);
+ if (compared > 0) return CP.gt;
+ else if (compared < 0) return CP.lt;
+ else return CP.eq;
+ }
+
// --- end additional functions
}
\ No newline at end of file
diff --git a/src/data-structures/binary-tree/diagrams/avl-tree-inserting.gif b/src/data-structures/binary-tree/diagrams/avl-tree-inserting.gif
new file mode 100644
index 0000000..46a3d48
Binary files /dev/null and b/src/data-structures/binary-tree/diagrams/avl-tree-inserting.gif differ
diff --git a/src/data-structures/binary-tree/diagrams/bst-rotation.gif b/src/data-structures/binary-tree/diagrams/bst-rotation.gif
new file mode 100644
index 0000000..a314ba8
Binary files /dev/null and b/src/data-structures/binary-tree/diagrams/bst-rotation.gif differ
diff --git a/src/data-structures/binary-tree/diagrams/segment-tree.png b/src/data-structures/binary-tree/diagrams/segment-tree.png
new file mode 100644
index 0000000..c02cc27
Binary files /dev/null and b/src/data-structures/binary-tree/diagrams/segment-tree.png differ
diff --git a/src/data-structures/binary-tree/segment-tree.ts b/src/data-structures/binary-tree/segment-tree.ts
index c6139d2..43bc89f 100644
--- a/src/data-structures/binary-tree/segment-tree.ts
+++ b/src/data-structures/binary-tree/segment-tree.ts
@@ -1,7 +1,15 @@
-export type SegmentTreeNodeVal = number;
+import type {SegmentTreeNodeVal} from '../types';
export class SegmentTreeNode {
+ constructor(start: number, end: number, sum: number, val?: SegmentTreeNodeVal | null) {
+ this._start = start;
+ this._end = end;
+ this._sum = sum;
+ this._val = val || null;
+ }
+
protected _start = 0;
+
get start(): number {
return this._start;
}
@@ -11,6 +19,7 @@ export class SegmentTreeNode {
}
protected _end = 0;
+
get end(): number {
return this._end;
}
@@ -20,6 +29,7 @@ export class SegmentTreeNode {
}
protected _val: SegmentTreeNodeVal | null = null;
+
get val(): SegmentTreeNodeVal | null {
return this._val;
}
@@ -29,6 +39,7 @@ export class SegmentTreeNode {
}
protected _sum = 0;
+
get sum(): number {
return this._sum;
}
@@ -38,6 +49,7 @@ export class SegmentTreeNode {
}
protected _left: SegmentTreeNode | null = null;
+
get left(): SegmentTreeNode | null {
return this._left;
}
@@ -47,6 +59,7 @@ export class SegmentTreeNode {
}
protected _right: SegmentTreeNode | null = null;
+
get right(): SegmentTreeNode | null {
return this._right;
}
@@ -54,23 +67,12 @@ export class SegmentTreeNode {
set right(v: SegmentTreeNode | null) {
this._right = v;
}
-
- constructor(start: number, end: number, sum: number, val?: SegmentTreeNodeVal | null) {
- this._start = start;
- this._end = end;
- this._sum = sum;
- this._val = val || null;
- }
}
export class SegmentTree {
protected _values: number[] = [];
protected _start = 0;
protected _end: number;
- protected _root: SegmentTreeNode | null;
- get root(): SegmentTreeNode | null {
- return this._root;
- }
constructor(values: number[], start?: number, end?: number) {
start = start || 0;
@@ -81,6 +83,12 @@ export class SegmentTree {
this._root = this.build(start, end);
}
+ protected _root: SegmentTreeNode | null;
+
+ get root(): SegmentTreeNode | null {
+ return this._root;
+ }
+
build(start: number, end: number): SegmentTreeNode {
if (start === end) {
return new SegmentTreeNode(start, end, this._values[start]);
diff --git a/src/data-structures/binary-tree/tree-multiset.ts b/src/data-structures/binary-tree/tree-multiset.ts
index d615a02..6e5449d 100644
--- a/src/data-structures/binary-tree/tree-multiset.ts
+++ b/src/data-structures/binary-tree/tree-multiset.ts
@@ -1,8 +1,5 @@
import {BST, BSTNode} from './bst';
-import {BinaryTreeNodeId} from './binary-tree';
-
-export type TreeMultiSetDeletedResult = { deleted: BSTNode | null, needBalanced: BSTNode | null };
-
+import type {BinaryTreeNodeId, TreeMultiSetDeletedResult} from '../types';
export class TreeMultiSet extends BST {
override createNode(id: BinaryTreeNodeId, val: T, count?: number): BSTNode {
diff --git a/src/data-structures/diagrams/README.md b/src/data-structures/diagrams/README.md
new file mode 100644
index 0000000..ae3e799
--- /dev/null
+++ b/src/data-structures/diagrams/README.md
@@ -0,0 +1,5 @@
+// 操作 常见名称 Ada Java JavaScript C++ Python Perl PHP Ruby // 尾部插入 inject, snoc Append offerLast push push_back append push
+array_push push // 头部插入 push, cons Prepend offerFirst unshift push_front appendleft unshift array_unshift unshift //
+尾部删除 eject Delete_Last pollLast pop pop_back pop pop array_pop pop // 头部删除 pop Delete_First pollFirst shift pop_front
+popleft shift array_shift shift // 查看尾部 Last_Element peekLast [length - 1] back [-1] $array[-1] end
+last // 查看头部 First_Element peekFirst [0] front [0] $array[0] reset first
diff --git a/src/data-structures/graph/abstract-graph.ts b/src/data-structures/graph/abstract-graph.ts
index 217aff4..7e953bf 100644
--- a/src/data-structures/graph/abstract-graph.ts
+++ b/src/data-structures/graph/abstract-graph.ts
@@ -1,60 +1,14 @@
import {arrayRemove, uuidV4} from '../../utils';
import {PriorityQueue} from '../priority-queue';
-
-export type VertexId = string | number;
-export type DijkstraResult =
- { distMap: Map, preMap: Map, seen: Set, paths: V[][], minDist: number, minPath: V[] }
- | null;
-
-export interface I_Graph {
-
- containsVertex(vertexOrId: V | VertexId): boolean;
-
- getVertex(vertexOrId: VertexId | V): V | null;
-
- getVertexId(vertexOrId: V | VertexId): VertexId;
-
- vertexSet(): Map;
-
- addVertex(v: V): boolean;
-
- removeVertex(vertexOrId: V | VertexId): boolean;
-
- removeAllVertices(vertices: V[] | VertexId[]): boolean;
-
- degreeOf(vertexOrId: V | VertexId): number;
-
- edgesOf(vertexOrId: V | VertexId): E[];
-
- containsEdge(src: V | VertexId, dest: V | VertexId): boolean;
-
- // containsEdge(e: E): boolean;
-
- getEdge(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;
-
- // getAllEdges(src: V, dest: V): E[];
-
- edgeSet(): E[];
-
- addEdge(edge: E): boolean;
-
- removeEdgeBetween(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;
-
- removeEdge(edge: E): E | null;
-
- // removeAllEdges(v1: VertexId | V, v2: VertexId | V): (E | null)[];
-
- // removeAllEdges(edges: E[] | [VertexId, VertexId]): boolean;
-
- setEdgeWeight(srcOrId: V | VertexId, destOrId: V | VertexId, weight: number): boolean;
-
- getMinPathBetween(v1: V | VertexId, v2: V | VertexId, isWeight?: boolean): V[] | null;
-
- getNeighbors(vertexOrId: V | VertexId): V[];
-}
+import type {DijkstraResult, IGraph, VertexId} from '../types';
export class AbstractVertex {
+ constructor(id: VertexId) {
+ this._id = id;
+ }
+
private _id: VertexId;
+
public get id(): VertexId {
return this._id;
}
@@ -62,15 +16,20 @@ export class AbstractVertex {
public set id(v: VertexId) {
this._id = v;
}
-
- constructor(id: VertexId) {
- this._id = id;
- }
}
export abstract class AbstractEdge {
+ static DEFAULT_EDGE_WEIGHT = 1;
+
+ protected constructor(weight?: number) {
+ if (weight === undefined) weight = AbstractEdge.DEFAULT_EDGE_WEIGHT;
+ this._weight = weight;
+ this._hashCode = uuidV4();
+ }
+
private _weight: number;
+
get weight(): number {
return this._weight;
}
@@ -88,18 +47,10 @@ export abstract class AbstractEdge {
set hashCode(v: string) {
this._hashCode = v;
}
-
- protected constructor(weight?: number) {
- if (weight === undefined) weight = AbstractEdge.DEFAULT_EDGE_WEIGHT;
- this._weight = weight;
- this._hashCode = uuidV4();
- }
-
- static DEFAULT_EDGE_WEIGHT = 1;
}
// Connected Component === Largest Connected Sub-Graph
-export abstract class AbstractGraph implements I_Graph {
+export abstract class AbstractGraph implements IGraph {
protected _vertices: Map = new Map();
@@ -192,7 +143,7 @@ export abstract class AbstractGraph vertex === neighbor);
+ arrayRemove(path, (vertex: AbstractVertex) => vertex === neighbor);
}
}
@@ -296,7 +247,7 @@ export abstract class AbstractGraph vertex === neighbor);
+ arrayRemove(path, (vertex: AbstractVertex) => vertex === neighbor);
}
}
@@ -338,7 +289,8 @@ export abstract class AbstractGraph {
for (const vertex of vertices) {
- const path: V[] = [vertex[1]];
- let parent = preMap.get(vertex[1]);
- while (parent) {
- path.push(parent);
- parent = preMap.get(parent);
+ const vertexOrId = vertex[1];
+
+ if (vertexOrId instanceof AbstractVertex) {
+ const path: V[] = [vertexOrId];
+ let parent = preMap.get(vertexOrId);
+ while (parent) {
+ path.push(parent);
+ parent = preMap.get(parent);
+ }
+ const reversed = path.reverse();
+ if (vertex[1] === minV) minPath = reversed;
+ paths.push(reversed);
}
- const reversed = path.reverse();
- if (vertex[1] === minV) minPath = reversed;
- paths.push(reversed);
}
};
@@ -449,7 +405,8 @@ export abstract class AbstractGraph({comparator: (a, b) => a.id - b.id});
@@ -460,15 +417,19 @@ export abstract class AbstractGraph {
for (const vertex of vertices) {
- const path: V[] = [vertex[1]];
- let parent = preMap.get(vertex[1]);
- while (parent) {
- path.push(parent);
- parent = preMap.get(parent);
+ const vertexOrId = vertex[1];
+ if (vertexOrId instanceof AbstractVertex) {
+ const path: V[] = [vertexOrId];
+ let parent = preMap.get(vertexOrId);
+ while (parent) {
+ path.push(parent);
+ parent = preMap.get(parent);
+ }
+ const reversed = path.reverse();
+ if (vertex[1] === minV) minPath = reversed;
+ paths.push(reversed);
}
- const reversed = path.reverse();
- if (vertex[1] === minV) minPath = reversed;
- paths.push(reversed);
+
}
};
@@ -551,7 +512,7 @@ export abstract class AbstractGraph {
- incomingEdgesOf(vertex: V): E[];
-
- outgoingEdgesOf(vertex: V): E[];
-
- inDegreeOf(vertexOrId: V | VertexId): number;
-
- outDegreeOf(vertexOrId: V | VertexId): number;
-
- getEdgeSrc(e: E): V | null;
-
- getEdgeDest(e: E): V | null;
-}
-
-// 0 means unknown, 1 means visiting, 2 means visited;
-export type TopologicalStatus = 0 | 1 | 2;
-
// Strongly connected, One direction connected, Weakly connected
-export class DirectedGraph extends AbstractGraph implements I_DirectedGraph {
+export class DirectedGraph extends AbstractGraph implements IDirectedGraph {
protected _outEdgeMap: Map = new Map();
@@ -120,12 +104,12 @@ export class DirectedGraph ext
const srcOutEdges = this._outEdgeMap.get(src);
if (srcOutEdges) {
- arrayRemove(srcOutEdges, edge => edge.dest === dest.id);
+ arrayRemove(srcOutEdges, (edge: DirectedEdge) => edge.dest === dest.id);
}
const destInEdges = this._inEdgeMap.get(dest);
if (destInEdges) {
- removed = arrayRemove(destInEdges, edge => edge.src === src.id)[0] || null;
+ removed = arrayRemove(destInEdges, (edge: DirectedEdge) => edge.src === src.id)[0] || null;
}
return removed;
}
@@ -137,12 +121,12 @@ export class DirectedGraph ext
if (src && dest) {
const srcOutEdges = this._outEdgeMap.get(src);
if (srcOutEdges && srcOutEdges.length > 0) {
- arrayRemove(srcOutEdges, edge => edge.src === src.id);
+ arrayRemove(srcOutEdges, (edge: DirectedEdge) => edge.src === src.id);
}
const destInEdges = this._inEdgeMap.get(dest);
if (destInEdges && destInEdges.length > 0) {
- removed = arrayRemove(destInEdges, edge => edge.dest === dest.id)[0];
+ removed = arrayRemove(destInEdges, (edge: DirectedEdge) => edge.dest === dest.id)[0];
}
}
@@ -194,7 +178,7 @@ export class DirectedGraph ext
return this.getVertex(e.dest);
}
- getDestinations(vertex: V | null): V[] {
+ getDestinations(vertex: V | VertexId | null): V[] {
if (vertex === null) {
return [];
}
@@ -215,7 +199,7 @@ export class DirectedGraph ext
* when stored with adjacency list time: O(V+E)
* when stored with adjacency matrix time: O(V^2)
*/
- topologicalSort(): V[] | null {
+ topologicalSort(): (V | VertexId)[] | null {
// vector> g;
// vector color;
// int last;
@@ -247,14 +231,14 @@ export class DirectedGraph ext
// }
// When judging whether there is a cycle in the undirected graph, all nodes with degree of **<= 1** are enqueued
// When judging whether there is a cycle in the directed graph, all nodes with **in degree = 0** are enqueued
- const statusMap: Map = new Map();
+ const statusMap: Map = new Map();
for (const entry of this._vertices) {
statusMap.set(entry[1], 0);
}
- const sorted: V[] = [];
+ const sorted: (V | VertexId)[] = [];
let hasCycle = false;
- const dfs = (cur: V) => {
+ const dfs = (cur: V | VertexId) => {
statusMap.set(cur, 1);
const children = this.getDestinations(cur);
for (const child of children) {
diff --git a/src/data-structures/graph/undirected-graph.ts b/src/data-structures/graph/undirected-graph.ts
index 34d8b48..14e9928 100644
--- a/src/data-structures/graph/undirected-graph.ts
+++ b/src/data-structures/graph/undirected-graph.ts
@@ -1,5 +1,6 @@
import {arrayRemove} from '../../utils';
-import {AbstractEdge, AbstractGraph, AbstractVertex, VertexId} from './abstract-graph';
+import {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';
+import type {VertexId} from '../types';
export class UndirectedVertex extends AbstractVertex {
constructor(id: VertexId) {
@@ -8,6 +9,11 @@ export class UndirectedVertex extends AbstractVertex {
}
export class UndirectedEdge extends AbstractEdge {
+ constructor(v1: VertexId, v2: VertexId, weight?: number) {
+ super(weight);
+ this._vertices = [v1, v2];
+ }
+
private _vertices: [VertexId, VertexId];
public get vertices() {
@@ -17,20 +23,15 @@ export class UndirectedEdge extends AbstractEdge {
public set vertices(v: [VertexId, VertexId]) {
this._vertices = v;
}
-
- constructor(v1: VertexId, v2: VertexId, weight?: number) {
- super(weight);
- this._vertices = [v1, v2];
- }
}
export class UndirectedGraph extends AbstractGraph {
+ protected _edges: Map = new Map();
+
constructor() {
super();
}
- protected _edges: Map = new Map();
-
getEdge(v1: V | null | VertexId, v2: V | null | VertexId): E | null {
let edges: E[] | undefined = [];
@@ -74,11 +75,11 @@ export class UndirectedGraph(v1Edges, e => e.vertices.includes(vertex2.id))[0] || null;
+ removed = arrayRemove(v1Edges, (e: UndirectedEdge) => e.vertices.includes(vertex2.id))[0] || null;
}
const v2Edges = this._edges.get(vertex2);
if (v2Edges) {
- arrayRemove(v2Edges, e => e.vertices.includes(vertex1.id));
+ arrayRemove(v2Edges, (e: UndirectedEdge) => e.vertices.includes(vertex1.id));
}
return removed;
}
diff --git a/src/data-structures/hash/coordinate-map.ts b/src/data-structures/hash/coordinate-map.ts
index ada0907..6d75d33 100644
--- a/src/data-structures/hash/coordinate-map.ts
+++ b/src/data-structures/hash/coordinate-map.ts
@@ -1,4 +1,4 @@
-export class CoordinateSet extends Map {
+export class CoordinateMap extends Map {
private readonly _joint: string = '_';
constructor(joint?: string) {
diff --git a/src/data-structures/hash/index.ts b/src/data-structures/hash/index.ts
index 5d31238..b4d9dd7 100644
--- a/src/data-structures/hash/index.ts
+++ b/src/data-structures/hash/index.ts
@@ -1 +1,6 @@
export * from './hash-table';
+export * from './coordinate-map';
+export * from './coordinate-set';
+export * from './pair';
+export * from './tree-map';
+export * from './tree-set';
diff --git a/src/data-structures/heap/heap.ts b/src/data-structures/heap/heap.ts
index c60e08a..ddda170 100644
--- a/src/data-structures/heap/heap.ts
+++ b/src/data-structures/heap/heap.ts
@@ -1,17 +1,8 @@
import {PriorityQueue} from '../priority-queue';
-
-export interface HeapOptions {
- priority?: (element: T) => number;
-}
-
-export interface HeapItem {
- priority: number;
- element: T | null;
-}
-
+import type {HeapItem, HeapOptions} from '../types';
/**
- * @copyright 2021 Pablo Rios
+ * @copyright 2021 Tyler Zeng
* @license MIT
*
* @abstract
diff --git a/src/data-structures/heap/max-heap.ts b/src/data-structures/heap/max-heap.ts
index b207cdf..75f9941 100644
--- a/src/data-structures/heap/max-heap.ts
+++ b/src/data-structures/heap/max-heap.ts
@@ -1,10 +1,11 @@
/**
- * @copyright 2020 Pablo Rios
+ * @copyright 2020 Tyler Zeng
* @license MIT
*/
-import {Heap, HeapItem, HeapOptions} from './heap';
+import {Heap} from './heap';
import {PriorityQueue} from '../priority-queue';
+import type {HeapItem, HeapOptions} from '../types';
/**
* @class MaxHeap
diff --git a/src/data-structures/heap/min-heap.ts b/src/data-structures/heap/min-heap.ts
index e639089..9e709b6 100644
--- a/src/data-structures/heap/min-heap.ts
+++ b/src/data-structures/heap/min-heap.ts
@@ -1,10 +1,11 @@
/**
- * @copyright 2020 Pablo Rios
+ * @copyright 2020 Tyler Zeng
* @license MIT
*/
-import {Heap, HeapItem, HeapOptions} from './heap';
+import {Heap} from './heap';
import {PriorityQueue} from '../priority-queue';
+import type {HeapItem, HeapOptions} from '../types';
/**
* @class MinHeap
diff --git a/src/data-structures/index.ts b/src/data-structures/index.ts
index 5a154bd..188bd8e 100644
--- a/src/data-structures/index.ts
+++ b/src/data-structures/index.ts
@@ -8,4 +8,5 @@ export * from './heap';
export * from './priority-queue';
export * from './matrix';
export * from './trie';
+export * from './types';
diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts
index fe411a6..81bf360 100644
--- a/src/data-structures/linked-list/doubly-linked-list.ts
+++ b/src/data-structures/linked-list/doubly-linked-list.ts
@@ -1,10 +1,4 @@
-// 操作 常见名称 Ada Java JavaScript C++ Python Perl PHP Ruby
-// 尾部插入 inject, snoc Append offerLast push push_back append push array_push push
-// 头部插入 push, cons Prepend offerFirst unshift push_front appendleft unshift array_unshift unshift
-// 尾部删除 eject Delete_Last pollLast pop pop_back pop pop array_pop pop
-// 头部删除 pop Delete_First pollFirst shift pop_front popleft shift array_shift shift
-// 查看尾部 Last_Element peekLast [length - 1] back [-1] $array[-1] end last
-// 查看头部 First_Element peekFirst [0] front [0] $array[0] reset first
+import type {DoublyLinkedListGetBy} from '../types';
export class DoublyLinkedListNode {
val: T;
@@ -18,8 +12,6 @@ export class DoublyLinkedListNode {
}
}
-export type DoublyLinkedListGetBy = 'node' | 'val';
-
export class DoublyLinkedList {
private _first: DoublyLinkedListNode | null = null;
private _last: DoublyLinkedListNode | null = null;
diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts
index 29ea7de..54686b1 100644
--- a/src/data-structures/linked-list/singly-linked-list.ts
+++ b/src/data-structures/linked-list/singly-linked-list.ts
@@ -1,16 +1,4 @@
-/** Type used for filter and find methods, returning a boolean */
-type TTestFunction = (
- data: NodeData,
- index: number,
- list: SinglyLinkedList,
-) => boolean;
-
-/** Type used for map and forEach methods, returning anything */
-type TMapFunction = (
- data: any,
- index: number,
- list: SinglyLinkedList,
-) => any;
+import type {TMapFunction, TTestFunction} from '../types';
/**
* The class which represents one link or node in a linked list
@@ -104,6 +92,23 @@ export class SinglyLinkedListNode {
*/
export class SinglyLinkedList {
+ /** The head of the list, the first node */
+ public head: SinglyLinkedListNode | null;
+ /** The tail of the list, the last node */
+ public tail: SinglyLinkedListNode | null;
+ /** Internal size reference */
+ private size: number;
+
+ constructor(...args: NodeData[]) {
+ this.head = null;
+ this.tail = null;
+ this.size = 0;
+
+ for (let i = 0; i < arguments.length; i++) {
+ this.append(args[i]);
+ }
+ }
+
/**
* The length of the list
*/
@@ -123,25 +128,6 @@ export class SinglyLinkedList {
return new SinglyLinkedList(...iterable);
}
- /** The head of the list, the first node */
- public head: SinglyLinkedListNode | null;
-
- /** The tail of the list, the last node */
- public tail: SinglyLinkedListNode | null;
-
- /** Internal size reference */
- private size: number;
-
- constructor(...args: NodeData[]) {
- this.head = null;
- this.tail = null;
- this.size = 0;
-
- for (let i = 0; i < arguments.length; i++) {
- this.append(args[i]);
- }
- }
-
/**
* Get the node val at a specified index, zero based
* ```ts
diff --git a/src/data-structures/matrix/matrix2d.ts b/src/data-structures/matrix/matrix2d.ts
index 20e81c2..cd6e360 100644
--- a/src/data-structures/matrix/matrix2d.ts
+++ b/src/data-structures/matrix/matrix2d.ts
@@ -16,21 +16,10 @@ export class Matrix2D {
}
}
- /**
- * Return the matrix values
- */
- public get m(): number[][] {
- return this._matrix
- }
-
public static get empty(): number[][] {
return [[], [], []]
}
- public get toVector(): Vector2D {
- return new Vector2D(this._matrix[0][0], this._matrix[1][0])
- }
-
/**
* Initialize an identity matrix
*/
@@ -41,6 +30,17 @@ export class Matrix2D {
[0, 0, 1]]
}
+ /**
+ * Return the matrix values
+ */
+ public get m(): number[][] {
+ return this._matrix
+ }
+
+ public get toVector(): Vector2D {
+ return new Vector2D(this._matrix[0][0], this._matrix[1][0])
+ }
+
public static add(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
const result = Matrix2D.empty
for (let i = 0; i < 3; i++) {
diff --git a/src/data-structures/matrix/navigator.ts b/src/data-structures/matrix/navigator.ts
index a80b5b6..3e27745 100644
--- a/src/data-structures/matrix/navigator.ts
+++ b/src/data-structures/matrix/navigator.ts
@@ -1,5 +1,4 @@
-type Direction = 'up' | 'right' | 'down' | 'left';
-type Turning = { [key in Direction]: Direction };
+import type {Direction, NavigatorParams, Turning} from '../types';
export class Character {
direction: Direction;
@@ -11,23 +10,12 @@ export class Character {
}
}
-interface NavigatorParams {
- matrix: T[][],
- turning: Turning,
- onMove: (cur: [number, number]) => void
- init: {
- cur: [number, number],
- charDir: Direction,
- VISITED: T,
- }
-}
-
export class Navigator {
+ onMove: (cur: [number, number]) => void;
private readonly _matrix: T[][];
private readonly _cur: [number, number];
private _character: Character;
private readonly _VISITED: T;
- onMove: (cur: [number, number]) => void;
constructor({matrix, turning, onMove, init: {cur, charDir, VISITED}}: NavigatorParams) {
this._matrix = matrix;
diff --git a/src/data-structures/matrix/vector2d.ts b/src/data-structures/matrix/vector2d.ts
index 27a1e3d..293dc22 100644
--- a/src/data-structures/matrix/vector2d.ts
+++ b/src/data-structures/matrix/vector2d.ts
@@ -1,4 +1,39 @@
-class Vector2D {
+export class Vector2D {
+ constructor(
+ public x: number = 0,
+ public y: number = 0,
+ public w: number = 1 // needed for matrix multiplication
+ ) {
+ }
+
+ /**
+ * Set x and y both to zero
+ */
+ public get isZero(): boolean {
+ return this.x === 0 && this.y === 0
+ }
+
+ /**
+ * The length / magnitude of the vector
+ */
+ public get length(): number {
+ return Math.sqrt((this.x * this.x) + (this.y * this.y))
+ }
+
+ /**
+ * The squared length of the vector
+ */
+ public get lengthSq(): number {
+ return (this.x * this.x) + (this.y * this.y)
+ }
+
+ /**
+ * Return the vector with rounded values
+ */
+ public get rounded(): Vector2D {
+ return new Vector2D(Math.round(this.x), Math.round(this.y))
+ }
+
public static add(vector1: Vector2D, vector2: Vector2D): Vector2D {
return new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y)
}
@@ -80,6 +115,22 @@ class Vector2D {
return (vector1.x * vector2.x) + (vector1.y * vector2.y)
}
+ // /**
+ // * Transform vectors based on the current tranformation matrices: translation, rotation and scale
+ // * @param vectors The vectors to transform
+ // */
+ // public static transform(vector: Vector2D, transformation: Matrix2D): Vector2D {
+ // return Matrix2D.multiplyByVector(transformation, vector)
+ // }
+
+ // /**
+ // * Transform vectors based on the current tranformation matrices: translation, rotation and scale
+ // * @param vectors The vectors to transform
+ // */
+ // public static transformList(vectors: Vector2D[], transformation: Matrix2D): Vector2D[] {
+ // return vectors.map(vector => Matrix2D.multiplyByVector(transformation, vector))
+ // }
+
/**
* The distance between this and the vector
*/
@@ -126,29 +177,6 @@ class Vector2D {
return new Vector2D(randX, randY)
}
- // /**
- // * Transform vectors based on the current tranformation matrices: translation, rotation and scale
- // * @param vectors The vectors to transform
- // */
- // public static transform(vector: Vector2D, transformation: Matrix2D): Vector2D {
- // return Matrix2D.multiplyByVector(transformation, vector)
- // }
-
- // /**
- // * Transform vectors based on the current tranformation matrices: translation, rotation and scale
- // * @param vectors The vectors to transform
- // */
- // public static transformList(vectors: Vector2D[], transformation: Matrix2D): Vector2D[] {
- // return vectors.map(vector => Matrix2D.multiplyByVector(transformation, vector))
- // }
-
- constructor(
- public x: number = 0,
- public y: number = 0,
- public w: number = 1 // needed for matrix multiplication
- ) {
- }
-
/**
* Check wether both x and y are zero
*/
@@ -156,34 +184,6 @@ class Vector2D {
this.x = 0
this.y = 0
}
-
- /**
- * Set x and y both to zero
- */
- public get isZero(): boolean {
- return this.x === 0 && this.y === 0
- }
-
- /**
- * The length / magnitude of the vector
- */
- public get length(): number {
- return Math.sqrt((this.x * this.x) + (this.y * this.y))
- }
-
- /**
- * The squared length of the vector
- */
- public get lengthSq(): number {
- return (this.x * this.x) + (this.y * this.y)
- }
-
- /**
- * Return the vector with rounded values
- */
- public get rounded(): Vector2D {
- return new Vector2D(Math.round(this.x), Math.round(this.y))
- }
}
export default Vector2D
\ No newline at end of file
diff --git a/src/data-structures/priority-queue/max-priority-queue.ts b/src/data-structures/priority-queue/max-priority-queue.ts
index 539e79a..e1a1b53 100644
--- a/src/data-structures/priority-queue/max-priority-queue.ts
+++ b/src/data-structures/priority-queue/max-priority-queue.ts
@@ -1,9 +1,10 @@
-import {PriorityQueue, PriorityQueueOptions} from './priority-queue';
+import {PriorityQueue} from './priority-queue';
+import type {PriorityQueueOptions} from '../types';
export class MaxPriorityQueue extends PriorityQueue {
- constructor(options: PriorityQueueOptions) {
+ constructor(options?: PriorityQueueOptions) {
super({
- nodes: options.nodes, comparator: (a: T, b: T) => {
+ nodes: options?.nodes, 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;
}
diff --git a/src/data-structures/priority-queue/min-priority-queue.ts b/src/data-structures/priority-queue/min-priority-queue.ts
index 74c4226..ae0a6dd 100644
--- a/src/data-structures/priority-queue/min-priority-queue.ts
+++ b/src/data-structures/priority-queue/min-priority-queue.ts
@@ -1,9 +1,10 @@
-import {PriorityQueue, PriorityQueueOptions} from './priority-queue';
+import {PriorityQueue} from './priority-queue';
+import type {PriorityQueueOptions} from '../types';
export class MinPriorityQueue extends PriorityQueue {
- constructor(options: PriorityQueueOptions) {
+ constructor(options?: PriorityQueueOptions) {
super({
- nodes: options.nodes, comparator: (a: T, b: T) => {
+ nodes: options?.nodes, 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;
}
diff --git a/src/data-structures/priority-queue/priority-queue.ts b/src/data-structures/priority-queue/priority-queue.ts
index 127769a..c5bc7b8 100644
--- a/src/data-structures/priority-queue/priority-queue.ts
+++ b/src/data-structures/priority-queue/priority-queue.ts
@@ -1,25 +1,8 @@
-export type PriorityQueueComparator = (a: T, b: T) => number;
-
-export interface PriorityQueueOptions {
- nodes?: T[];
- isFix?: boolean;
- comparator: PriorityQueueComparator;
-}
-
-export type PriorityQueueDFSOrderPattern = 'pre' | 'in' | 'post';
+import type {PriorityQueueComparator, PriorityQueueDFSOrderPattern, PriorityQueueOptions} from '../types';
export class PriorityQueue {
protected nodes: T[] = [];
- get size(): number {
- return this.nodes.length;
- }
-
- protected readonly _comparator: PriorityQueueComparator = (a: T, b: T) => {
- const aKey = a as unknown as number, bKey = b as unknown as number;
- return aKey - bKey;
- };
-
constructor(options: PriorityQueueOptions) {
const {nodes, comparator, isFix = true} = options;
this._comparator = comparator;
@@ -31,64 +14,18 @@ export class PriorityQueue {
}
}
- protected _compare(a: number, b: number) {
- return this._comparator(this.nodes[a], this.nodes[b]) > 0;
+ get size(): number {
+ return this.nodes.length;
}
- protected _swap(a: number, b: number) {
- const temp = this.nodes[a];
- this.nodes[a] = this.nodes[b];
- this.nodes[b] = temp;
+ static heapify(options: PriorityQueueOptions) {
+ const heap = new PriorityQueue(options);
+ heap._fix();
+ return heap;
}
- protected _isValidIndex(index: number): boolean {
- return index > -1 && index < this.nodes.length;
- }
-
- protected _getParent(child: number): number {
- return Math.floor((child - 1) / 2);
- }
-
- protected _getLeft(parent: number): number {
- return (2 * parent) + 1;
- }
-
- protected _getRight(parent: number): number {
- return (2 * parent) + 2;
- }
-
- protected _getComparedChild(parent: number) {
- let min = parent;
- const left = this._getLeft(parent), right = this._getRight(parent);
-
- if (left < this.size && this._compare(min, left)) {
- min = left;
- }
- if (right < this.size && this._compare(min, right)) {
- min = right;
- }
- return min;
- }
-
- protected _heapifyUp(start: number) {
- while (start > 0 && this._compare(this._getParent(start), start)) {
- const parent = this._getParent(start);
- this._swap(start, parent);
- start = parent;
- }
- }
-
- protected _heapifyDown(start: number) {
- let min = this._getComparedChild(start);
- while (this._compare(start, min)) {
- this._swap(min, start);
- start = min;
- min = this._getComparedChild(start);
- }
- }
-
- protected _fix() {
- for (let i = Math.floor(this.size / 2); i > -1; i--) this._heapifyDown(i);
+ static isPriorityQueueified(options: Omit, 'isFix'>) {
+ return new PriorityQueue({...options, isFix: true}).isValid();
}
offer(node: T) {
@@ -194,14 +131,69 @@ export class PriorityQueue {
return visitedNode;
}
- static heapify(options: PriorityQueueOptions