mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 04:44:04 +00:00
[BinaryTree] isMergeDuplicatedNodeById removed, [MapGraph] MapGraph added
This commit is contained in:
parent
f3b2398d20
commit
26ab0be17b
21
LICENSE
21
LICENSE
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -141,15 +141,8 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
*/
|
||||
protected constructor(options?: AbstractBinaryTreeOptions) {
|
||||
if (options !== undefined) {
|
||||
const {
|
||||
loopType = LoopType.ITERATIVE,
|
||||
isMergeDuplicatedNodeById = true
|
||||
} = options;
|
||||
this._isMergeDuplicatedNodeById = isMergeDuplicatedNodeById;
|
||||
const {loopType = LoopType.ITERATIVE} = options;
|
||||
this._loopType = loopType;
|
||||
} else {
|
||||
this._isMergeDuplicatedNodeById = true;
|
||||
this._loopType = LoopType.ITERATIVE;
|
||||
}
|
||||
this.clear();
|
||||
}
|
||||
|
@ -172,13 +165,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return this._loopType;
|
||||
}
|
||||
|
||||
// TODO this variable may be moved to TreeMultiset
|
||||
private _isMergeDuplicatedNodeById: boolean = true;
|
||||
|
||||
get isMergeDuplicatedNodeById(): boolean {
|
||||
return this._isMergeDuplicatedNodeById;
|
||||
}
|
||||
|
||||
private _visitedId: BinaryTreeNodeId[] = [];
|
||||
|
||||
get visitedId(): BinaryTreeNodeId[] {
|
||||
|
@ -268,7 +254,8 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
while (queue.length > 0) {
|
||||
const cur = queue.shift();
|
||||
if (cur) {
|
||||
const inserted = this.addTo(newNode, cur);
|
||||
if (newNode && cur.id === newNode.id) return;
|
||||
const inserted = this._addTo(newNode, cur);
|
||||
if (inserted !== undefined) return inserted;
|
||||
if (cur.left) queue.push(cur.left);
|
||||
if (cur.right) queue.push(cur.right);
|
||||
|
@ -310,39 +297,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return inserted;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function adds a new node to the left or right child of a parent node, updating the size of the tree if
|
||||
* necessary.
|
||||
* @param {N | null} newNode - The `newNode` parameter represents the node that you want to add to the tree. It can be
|
||||
* either a node object (`N`) or `null`.
|
||||
* @param {N} parent - The `parent` parameter represents the parent node to which the new node will be added as a
|
||||
* child.
|
||||
* @returns either the left child node, the right child node, or undefined.
|
||||
*/
|
||||
addTo(newNode: N | null, parent: N): N | null | undefined {
|
||||
if (parent) {
|
||||
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
|
||||
// In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
|
||||
if (parent.left === undefined) {
|
||||
parent.left = newNode;
|
||||
if (newNode) {
|
||||
this._setSize(this.size + 1);
|
||||
}
|
||||
return parent.left;
|
||||
} else if (parent.right === undefined) {
|
||||
parent.right = newNode;
|
||||
if (newNode) {
|
||||
this._setSize(this.size + 1);
|
||||
}
|
||||
return parent.right;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `addMany` function adds multiple nodes to a tree data structure and returns an array of the inserted nodes or
|
||||
* null/undefined values.
|
||||
|
@ -357,31 +311,27 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
const inserted: (N | null | undefined)[] = [];
|
||||
const map: Map<N | BinaryTreeNodeId | null, number> = new Map();
|
||||
|
||||
if (this.isMergeDuplicatedNodeById) {
|
||||
for (const idOrNode of idsOrNodes) map.set(idOrNode, (map.get(idOrNode) ?? 0) + 1);
|
||||
}
|
||||
for (const idOrNode of idsOrNodes) map.set(idOrNode, (map.get(idOrNode) ?? 0) + 1);
|
||||
|
||||
for (let i = 0; i < idsOrNodes.length; i++) {
|
||||
const idOrNode = idsOrNodes[i];
|
||||
if (idOrNode instanceof AbstractBinaryTreeNode) {
|
||||
inserted.push(this.add(idOrNode.id, idOrNode.val));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (idOrNode === null) {
|
||||
inserted.push(this.add(null));
|
||||
continue;
|
||||
}
|
||||
|
||||
const val = data?.[i];
|
||||
if (this.isMergeDuplicatedNodeById) {
|
||||
if (map.has(idOrNode)) {
|
||||
inserted.push(this.add(idOrNode, val));
|
||||
map.delete(idOrNode);
|
||||
if (map.has(idOrNode)) {
|
||||
if (idOrNode instanceof AbstractBinaryTreeNode) {
|
||||
inserted.push(this.add(idOrNode.id, idOrNode.val));
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (idOrNode === null) {
|
||||
inserted.push(this.add(null));
|
||||
continue;
|
||||
}
|
||||
|
||||
const val = data?.[i];
|
||||
|
||||
inserted.push(this.add(idOrNode, val));
|
||||
map.delete(idOrNode);
|
||||
}
|
||||
|
||||
}
|
||||
return inserted;
|
||||
}
|
||||
|
@ -1001,11 +951,11 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
}
|
||||
|
||||
DFSIterative(): BinaryTreeNodeId[];
|
||||
|
||||
|
||||
// --- start additional methods ---
|
||||
|
||||
DFSIterative(): BinaryTreeNodeId[];
|
||||
|
||||
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
|
||||
|
||||
DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): N[];
|
||||
|
@ -1304,6 +1254,40 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function adds a new node to a binary tree if there is an available position.
|
||||
* @param {N | null} newNode - The `newNode` parameter is of type `N | null`, which means it can either be a node of
|
||||
* type `N` or `null`. It represents the node that you want to add to the binary tree.
|
||||
* @param {N} parent - The parent parameter is of type N, which represents a node in a binary tree.
|
||||
* @returns either the left or right child node of the parent node, depending on which child is available for adding
|
||||
* the new node. If a new node is added, the function also updates the size of the binary tree. If neither the left nor
|
||||
* right child is available, the function returns undefined. If the parent node is null, the function also returns
|
||||
* undefined.
|
||||
*/
|
||||
protected _addTo(newNode: N | null, parent: N): N | null | undefined {
|
||||
if (parent) {
|
||||
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
|
||||
// In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
|
||||
if (parent.left === undefined) {
|
||||
parent.left = newNode;
|
||||
if (newNode) {
|
||||
this._setSize(this.size + 1);
|
||||
}
|
||||
return parent.left;
|
||||
} else if (parent.right === undefined) {
|
||||
parent.right = newNode;
|
||||
if (newNode) {
|
||||
this._setSize(this.size + 1);
|
||||
}
|
||||
return parent.right;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the loop type for a protected variable.
|
||||
* @param {LoopType} value - The value parameter is of type LoopType.
|
||||
|
@ -1344,14 +1328,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
|
|||
this._visitedLeftSum = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the value of a protected property called "_isMergeDuplicatedNodeById".
|
||||
* @param {boolean} value - The value parameter is a boolean value that determines whether the isMergeDuplicatedNodeById
|
||||
* property should be set to true or false.
|
||||
*/
|
||||
protected _setIsDuplicatedVal(value: boolean) {
|
||||
this._isMergeDuplicatedNodeById = 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
|
||||
|
|
|
@ -50,7 +50,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* TreeMultiset.
|
||||
*/
|
||||
constructor(options?: TreeMultisetOptions) {
|
||||
super({...options, isMergeDuplicatedNodeById: true});
|
||||
super({...options});
|
||||
}
|
||||
|
||||
private _count = 0;
|
||||
|
@ -178,15 +178,15 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
}
|
||||
|
||||
/**
|
||||
* The function adds a new node to a binary tree as the left or right child of a given parent node.
|
||||
* @param {N | null} newNode - The `newNode` parameter represents the node that you want to add to the tree. It can be
|
||||
* either a node object (`N`) or `null`.
|
||||
* The function adds a new node to a binary tree if there is an available slot on the left or right side of the parent
|
||||
* node.
|
||||
* @param {N | null} newNode - The `newNode` parameter represents the node that needs to be added to the tree. It can
|
||||
* be either a node object (`N`) or `null`.
|
||||
* @param {N} parent - The `parent` parameter represents the parent node to which the new node will be added as a
|
||||
* child.
|
||||
* @returns either the left or right child node that was added to the parent node. It can also return `null` or
|
||||
* `undefined` in certain cases.
|
||||
* @returns The method returns either the `parent.left`, `parent.right`, or `undefined`.
|
||||
*/
|
||||
override addTo(newNode: N | null, parent: N): N | null | undefined {
|
||||
override _addTo(newNode: N | null, parent: N): N | null | undefined {
|
||||
if (parent) {
|
||||
if (parent.left === undefined) {
|
||||
parent.left = newNode;
|
||||
|
@ -225,32 +225,28 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
const inserted: (N | null | undefined)[] = [];
|
||||
const map: Map<N | BinaryTreeNodeId, number> = new Map();
|
||||
|
||||
if (this.isMergeDuplicatedNodeById) {
|
||||
for (const idOrNode of idsOrNodes) map.set(idOrNode, (map.get(idOrNode) ?? 0) + 1);
|
||||
}
|
||||
for (const idOrNode of idsOrNodes) map.set(idOrNode, (map.get(idOrNode) ?? 0) + 1);
|
||||
|
||||
for (let i = 0; i < idsOrNodes.length; i++) {
|
||||
const idOrNode = idsOrNodes[i];
|
||||
if (idOrNode instanceof TreeMultisetNode) {
|
||||
inserted.push(this.add(idOrNode.id, idOrNode.val, idOrNode.count));
|
||||
continue;
|
||||
}
|
||||
if (map.has(idOrNode)) {
|
||||
|
||||
if (idOrNode === null) {
|
||||
inserted.push(this.add(NaN, null, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
const count = this.isMergeDuplicatedNodeById ? map.get(idOrNode) : 1;
|
||||
const val = data?.[i];
|
||||
if (this.isMergeDuplicatedNodeById) {
|
||||
if (map.has(idOrNode)) {
|
||||
inserted.push(this.add(idOrNode, val, count));
|
||||
map.delete(idOrNode);
|
||||
if (idOrNode instanceof TreeMultisetNode) {
|
||||
inserted.push(this.add(idOrNode.id, idOrNode.val, idOrNode.count));
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
inserted.push(this.add(idOrNode, val, 1));
|
||||
|
||||
if (idOrNode === null) {
|
||||
inserted.push(this.add(NaN, null, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
const val = data?.[i], count = map.get(idOrNode);
|
||||
|
||||
inserted.push(this.add(idOrNode, val, count));
|
||||
map.delete(idOrNode);
|
||||
}
|
||||
|
||||
}
|
||||
return inserted;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {PriorityQueue} from '../priority-queue';
|
|||
import type {DijkstraResult, VertexId} from '../types';
|
||||
import {IAbstractGraph} from '../interfaces';
|
||||
|
||||
export abstract class AbstractVertex<T = number> {
|
||||
export abstract class AbstractVertex<T = any> {
|
||||
|
||||
/**
|
||||
* The function is a protected constructor that takes an id and an optional value as parameters.
|
||||
|
@ -45,7 +45,7 @@ export abstract class AbstractVertex<T = number> {
|
|||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractEdge<T = number> {
|
||||
export abstract class AbstractEdge<T = any> {
|
||||
|
||||
/**
|
||||
* The above function is a protected constructor that initializes the weight, value, and hash code properties of an
|
||||
|
@ -103,7 +103,7 @@ export abstract class AbstractEdge<T = number> {
|
|||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractGraph<V extends AbstractVertex<any>, E extends 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> {
|
||||
|
@ -604,9 +604,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any>, E extends Abs
|
|||
const srcVertex = this._getVertex(src);
|
||||
const destVertex = dest ? this._getVertex(dest) : null;
|
||||
|
||||
if (!srcVertex) {
|
||||
return null;
|
||||
}
|
||||
if (!srcVertex) return null;
|
||||
|
||||
for (const vertex of vertices) {
|
||||
const vertexOrId = vertex[1];
|
||||
|
@ -619,6 +617,11 @@ export abstract class AbstractGraph<V extends AbstractVertex<any>, E extends Abs
|
|||
distMap.set(srcVertex, 0);
|
||||
preMap.set(srcVertex, null);
|
||||
|
||||
/**
|
||||
* The function `getPaths` retrieves all paths from vertices to a specified minimum vertex.
|
||||
* @param {V | null} minV - The parameter `minV` is of type `V | null`. It represents the minimum vertex value or
|
||||
* null.
|
||||
*/
|
||||
const getPaths = (minV: V | null) => {
|
||||
for (const vertex of vertices) {
|
||||
const vertexOrId = vertex[1];
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './abstract-graph';
|
||||
export * from './directed-graph';
|
||||
export * from './undirected-graph';
|
||||
export * from './map-graph';
|
||||
|
|
|
@ -53,8 +53,6 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
get visitedLeftSum(): number[]
|
||||
|
||||
get isMergeDuplicatedNodeById(): boolean
|
||||
|
||||
get root(): N | null
|
||||
|
||||
get size(): number
|
||||
|
@ -67,8 +65,6 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
|
|||
|
||||
add(id: BinaryTreeNodeId | N, val?: N['val']): N | null | undefined
|
||||
|
||||
addTo(newNode: N | null, parent: N): 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
|
||||
|
|
|
@ -8,5 +8,4 @@ export interface ITreeMultisetNode<T, NEIGHBOR extends ITreeMultisetNode<T, NEIG
|
|||
|
||||
export interface ITreeMultiset<N extends TreeMultisetNode<N['val'], N>> extends IAVLTree<N> {
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export class TreeNode<T = number> {
|
||||
export class TreeNode<T = any> {
|
||||
constructor(id: string, value?: T, children?: TreeNode<T>[]) {
|
||||
this._id = id;
|
||||
this._value = value || undefined;
|
||||
|
|
|
@ -37,5 +37,4 @@ export type AbstractBinaryTreeNodeNested<T> = AbstractBinaryTreeNode<T, Abstract
|
|||
|
||||
export type AbstractBinaryTreeOptions = {
|
||||
loopType?: LoopType,
|
||||
isMergeDuplicatedNodeById?: boolean
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
export type VertexId = string | number;
|
||||
export type EdgeId = string;
|
||||
export type DijkstraResult<V> =
|
||||
{ distMap: Map<V, number>, preMap: Map<V, V | null>, seen: Set<V>, paths: V[][], minDist: number, minPath: V[] }
|
||||
{ distMap: Map<V, number>, distPaths?: Map<V, V[]> ,preMap: Map<V, V | null>, seen: Set<V>, paths: V[][], minDist: number, minPath: V[] }
|
||||
| null;
|
||||
|
|
|
@ -4,6 +4,7 @@ export * from './avl-tree';
|
|||
export * from './segment-tree';
|
||||
export * from './tree-multiset';
|
||||
export * from './abstract-graph';
|
||||
export * from './map-graph';
|
||||
export * from './abstract-binary-tree';
|
||||
export * from './rb-tree';
|
||||
export * from './directed-graph';
|
||||
|
|
|
@ -3,6 +3,4 @@ import {AVLTreeOptions} from './avl-tree';
|
|||
|
||||
export type TreeMultisetNodeNested<T> = TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type TreeMultisetOptions = Omit<AVLTreeOptions, 'isMergeDuplicatedNodeById'> & {
|
||||
isMergeDuplicatedNodeById: true,
|
||||
}
|
||||
export type TreeMultisetOptions = Omit<AVLTreeOptions, 'isMergeDuplicatedNodeById'> & {}
|
||||
|
|
Loading…
Reference in a new issue