remove createNode function from every Binary Tree Nodes

This commit is contained in:
Revone 2023-08-28 20:04:43 +08:00
parent 61f465fe99
commit 87b7e420b5
10 changed files with 213 additions and 284 deletions

365
README.md
View file

@ -3,6 +3,190 @@
## Brief
Javascript & TypeScript Data Structure Library.
## Algorithms list only a few out, you can discover more in API docs
DFS, DFSIterative, BFS, morris, Bellman-Ford Algorithm, Dijkstra's Algorithm, Floyd-Warshall Algorithm, Tarjan's Algorithm
# How
## install
### yarn
```bash
yarn add data-structure-typed
```
### npm
```bash
npm install data-structure-typed
```
### Binary Search Tree (BST) snippet
#### TS
```typescript
import {BST, BSTNode} from 'data-structure-typed';
const bst = new BST();
bst.add(11);
bst.add(3);
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
bst.size === 16; // true
bst.has(6); // true
const node6 = bst.get(6);
bst.getHeight(6) === 2; // true
bst.getHeight() === 5; // true
bst.getDepth(6) === 3; // true
const leftMost = bst.getLeftMost();
leftMost?.id === 1; // true
expect(leftMost?.id).toBe(1);
bst.remove(6);
bst.get(6); // null
bst.isAVLBalanced(); // true or false
const bfsIDs = bst.BFS();
bfsIDs[0] === 11; // true
expect(bfsIDs[0]).toBe(11);
const objBST = new BST<BSTNode<{ id: number, keyA: number }>>();
objBST.add(11, {id: 11, keyA: 11});
objBST.add(3, {id: 3, keyA: 3});
objBST.addMany([{id: 15, keyA: 15}, {id: 1, keyA: 1}, {id: 8, keyA: 8},
{id: 13, keyA: 13}, {id: 16, keyA: 16}, {id: 2, keyA: 2},
{id: 6, keyA: 6}, {id: 9, keyA: 9}, {id: 12, keyA: 12},
{id: 14, keyA: 14}, {id: 4, keyA: 4}, {id: 7, keyA: 7},
{id: 10, keyA: 10}, {id: 5, keyA: 5}]);
objBST.remove(11);
const avlTree = new AVLTree();
avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5])
avlTree.isAVLBalanced(); // true
avlTree.remove(10);
avlTree.isAVLBalanced(); // true
```
#### JS
```javascript
const {BST, BSTNode} = require('data-structure-typed');
const bst = new BST();
bst.add(11);
bst.add(3);
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
bst.size === 16; // true
bst.has(6); // true
const node6 = bst.get(6);
bst.getHeight(6) === 2; // true
bst.getHeight() === 5; // true
bst.getDepth(6) === 3; // true
const leftMost = bst.getLeftMost();
leftMost?.id === 1; // true
expect(leftMost?.id).toBe(1);
bst.remove(6);
bst.get(6); // null
bst.isAVLBalanced(); // true or false
const bfsIDs = bst.BFS();
bfsIDs[0] === 11; // true
expect(bfsIDs[0]).toBe(11);
const objBST = new BST();
objBST.add(11, {id: 11, keyA: 11});
objBST.add(3, {id: 3, keyA: 3});
objBST.addMany([{id: 15, keyA: 15}, {id: 1, keyA: 1}, {id: 8, keyA: 8},
{id: 13, keyA: 13}, {id: 16, keyA: 16}, {id: 2, keyA: 2},
{id: 6, keyA: 6}, {id: 9, keyA: 9}, {id: 12, keyA: 12},
{id: 14, keyA: 14}, {id: 4, keyA: 4}, {id: 7, keyA: 7},
{id: 10, keyA: 10}, {id: 5, keyA: 5}]);
objBST.remove(11);
const avlTree = new AVLTree();
avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5])
avlTree.isAVLBalanced(); // true
avlTree.remove(10);
avlTree.isAVLBalanced(); // true
```
### Directed Graph simple snippet
#### TS or JS
```typescript
import {DirectedGraph} from 'data-structure-typed';
const graph = new DirectedGraph();
graph.addVertex('A');
graph.addVertex('B');
graph.hasVertex('A'); // true
graph.hasVertex('B'); // true
graph.hasVertex('C'); // false
graph.addEdge('A', 'B');
graph.hasEdge('A', 'B'); // true
graph.hasEdge('B', 'A'); // false
graph.removeEdgeSrcToDest('A', 'B');
graph.hasEdge('A', 'B'); // false
graph.addVertex('C');
graph.addEdge('A', 'B');
graph.addEdge('B', 'C');
const topologicalOrderIds = graph.topologicalSort(); // ['A', 'B', 'C']
```
### Undirected Graph snippet
#### TS or JS
```typescript
import {UndirectedGraph} from 'data-structure-typed';
const graph = new UndirectedGraph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.removeVertex('C');
graph.addEdge('A', 'B');
graph.addEdge('B', 'D');
const dijkstraResult = graph.dijkstra('A');
Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.id) // ['A', 'B', 'D']
```
[API Docs](https://data-structure-typed-docs.vercel.app)
[Live Examples](https://data-structure-typed-examples.vercel.app)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/dfs-pre-order.webp)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/test-graphs.webp)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/cut-off-trees-for-golf.webp)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/parenthesis-check.webp)
<a href="https://data-structure-typed-examples.vercel.app" target="_blank">Live Examples</a>
## API docs
[//]: # ([Examples Repository]&#40;https://github.com/zrwusa/data-structure-typed-examples&#41;)
<a href="https://github.com/zrwusa/data-structure-typed-examples" target="_blank">Examples Repository</a>
Meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a
wide range of data structures
@ -199,187 +383,6 @@ wide range of data structures
</tbody>
</table>
## Algorithms list only a few out, you can discover more in API docs
DFS, DFSIterative, BFS, morris, Bellman-Ford Algorithm, Dijkstra's Algorithm, Floyd-Warshall Algorithm, Tarjan's Algorithm
# How
## install
### yarn
```bash
yarn add data-structure-typed
```
### npm
```bash
npm install data-structure-typed
```
### Binary Search Tree (BST) snippet
#### TS
```typescript
import {BST, BSTNode} from 'data-structure-typed';
const bst = new BST();
bst.add(11);
bst.add(3);
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
bst.size === 16; // true
bst.has(6); // true
const node6 = bst.get(6);
bst.getHeight(6) === 2; // true
bst.getHeight() === 5; // true
bst.getDepth(6) === 3; // true
const leftMost = bst.getLeftMost();
leftMost?.id === 1; // true
expect(leftMost?.id).toBe(1);
bst.remove(6);
bst.get(6); // null
bst.isAVLBalanced(); // true or false
const bfsIDs = bst.BFS();
bfsIDs[0] === 11; // true
expect(bfsIDs[0]).toBe(11);
const objBST = new BST<BSTNode<{ id: number, keyA: number }>>();
objBST.add(11, {id: 11, keyA: 11});
objBST.add(3, {id: 3, keyA: 3});
objBST.addMany([{id: 15, keyA: 15}, {id: 1, keyA: 1}, {id: 8, keyA: 8},
{id: 13, keyA: 13}, {id: 16, keyA: 16}, {id: 2, keyA: 2},
{id: 6, keyA: 6}, {id: 9, keyA: 9}, {id: 12, keyA: 12},
{id: 14, keyA: 14}, {id: 4, keyA: 4}, {id: 7, keyA: 7},
{id: 10, keyA: 10}, {id: 5, keyA: 5}]);
objBST.remove(11);
const avlTree = new AVLTree();
avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5])
avlTree.isAVLBalanced(); // true
avlTree.remove(10);
avlTree.isAVLBalanced(); // true
```
#### JS
```javascript
const {BST, BSTNode} = require('data-structure-typed');
const bst = new BST();
bst.add(11);
bst.add(3);
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
bst.size === 16; // true
bst.has(6); // true
const node6 = bst.get(6);
bst.getHeight(6) === 2; // true
bst.getHeight() === 5; // true
bst.getDepth(6) === 3; // true
const leftMost = bst.getLeftMost();
leftMost?.id === 1; // true
expect(leftMost?.id).toBe(1);
bst.remove(6);
bst.get(6); // null
bst.isAVLBalanced(); // true or false
const bfsIDs = bst.BFS();
bfsIDs[0] === 11; // true
expect(bfsIDs[0]).toBe(11);
const objBST = new BST();
objBST.add(11, {id: 11, keyA: 11});
objBST.add(3, {id: 3, keyA: 3});
objBST.addMany([{id: 15, keyA: 15}, {id: 1, keyA: 1}, {id: 8, keyA: 8},
{id: 13, keyA: 13}, {id: 16, keyA: 16}, {id: 2, keyA: 2},
{id: 6, keyA: 6}, {id: 9, keyA: 9}, {id: 12, keyA: 12},
{id: 14, keyA: 14}, {id: 4, keyA: 4}, {id: 7, keyA: 7},
{id: 10, keyA: 10}, {id: 5, keyA: 5}]);
objBST.remove(11);
const avlTree = new AVLTree();
avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5])
avlTree.isAVLBalanced(); // true
avlTree.remove(10);
avlTree.isAVLBalanced(); // true
```
### Directed Graph simple snippet
#### TS or JS
```typescript
import {DirectedGraph} from 'data-structure-typed';
const graph = new DirectedGraph();
graph.addVertex('A');
graph.addVertex('B');
graph.hasVertex('A'); // true
graph.hasVertex('B'); // true
graph.hasVertex('C'); // false
graph.addEdge('A', 'B');
graph.hasEdge('A', 'B'); // true
graph.hasEdge('B', 'A'); // false
graph.removeEdgeSrcToDest('A', 'B');
graph.hasEdge('A', 'B'); // false
graph.addVertex('C');
graph.addEdge('A', 'B');
graph.addEdge('B', 'C');
const topologicalOrderIds = graph.topologicalSort(); // ['A', 'B', 'C']
```
### Undirected Graph snippet
#### TS or JS
```typescript
import {UndirectedGraph} from 'data-structure-typed';
const graph = new UndirectedGraph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.removeVertex('C');
graph.addEdge('A', 'B');
graph.addEdge('B', 'D');
const dijkstraResult = graph.dijkstra('A');
Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.id) // ['A', 'B', 'D']
```
[API Docs](https://data-structure-typed-docs.vercel.app)
[Live Examples](https://data-structure-typed-examples.vercel.app)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/dfs-pre-order.webp)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/test-graphs.webp)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/cut-off-trees-for-golf.webp)
![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/examples/parenthesis-check.webp)
<a href="https://data-structure-typed-examples.vercel.app" target="_blank">Live Examples</a>
## API docs
[//]: # ([Examples Repository]&#40;https://github.com/zrwusa/data-structure-typed-examples&#41;)
<a href="https://github.com/zrwusa/data-structure-typed-examples" target="_blank">Examples Repository</a>
# Why

View file

@ -140,44 +140,6 @@ export abstract class AbstractBinaryTreeNode<T = any, FAMILY extends AbstractBin
}
}
}
abstract createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY
/**
* The function swaps the location of two nodes in a binary tree.
* @param {FAMILY} destNode - The `swapNode` parameter is of type `FAMILY`, which represents a node in a family tree.
* @returns the `swapNode` object after swapping its properties with the properties of `this` object.
*/
swapLocation(destNode: FAMILY): FAMILY {
const {val, count, height, id} = destNode;
const tempNode = this.createNode(id, val, count);
tempNode.height = height;
if (tempNode instanceof AbstractBinaryTreeNode) {
// TODO should we consider the left, right children?
destNode.id = this.id;
destNode.val = this.val;
destNode.count = this.count;
destNode.height = this.height;
this.id = tempNode.id;
this.val = tempNode.val;
this.count = tempNode.count;
this.height = tempNode.height;
}
return destNode;
}
/**
* The `clone` function returns a new instance of the `FAMILY` class with the same `id`, `val`, and `count` properties.
* @returns The `clone()` method is returning a new instance of the `FAMILY` class with the same `id`, `val`, and
* `count` values as the current instance.
*/
clone(): FAMILY | null {
return this.createNode(this.id, this.val, this.count);
}
}
export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'], N> = AbstractBinaryTreeNode> implements IAbstractBinaryTree<N> {
@ -273,6 +235,32 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
abstract createNode(id: BinaryTreeNodeId, val?: N['val'], count?: number): N | null ;
swapLocation(srcNode: N, destNode: N): N {
const {val, count, height, id} = destNode;
const tempNode = this.createNode(id, val, count);
if (tempNode) {
tempNode.height = height;
if (tempNode instanceof AbstractBinaryTreeNode) {
// TODO should we consider the left, right children?
destNode.id = srcNode.id;
destNode.val = srcNode.val;
destNode.count = srcNode.count;
destNode.height = srcNode.height;
srcNode.id = tempNode.id;
srcNode.val = tempNode.val;
srcNode.count = tempNode.count;
srcNode.height = tempNode.height;
}
}
return destNode;
}
/**
* The clear function resets the state of an object by setting its properties to their initial values.
*/
@ -499,7 +487,7 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;
if (leftSubTreeRightMost) {
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
orgCurrent = curr.swapLocation(leftSubTreeRightMost);
orgCurrent = this.swapLocation(curr, leftSubTreeRightMost);
if (parentOfLeftSubTreeMax) {
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;

View file

@ -10,9 +10,6 @@ import type {AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BinaryT
import {IAVLTree, IAVLTreeNode} from '../interfaces';
export class AVLTreeNode<T = any, FAMILY extends AVLTreeNode<T, FAMILY> = AVLTreeNodeNested<T>> extends BSTNode<T, FAMILY> implements IAVLTreeNode<T, FAMILY> {
override createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY {
return new AVLTreeNode(id, val, count) as FAMILY;
}
}
export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends BST<N> implements IAVLTree<N> {

View file

@ -13,20 +13,6 @@ import {IBinaryTree, IBinaryTreeNode} from '../interfaces/binary-tree';
export class BinaryTreeNode<T = any, FAMILY extends BinaryTreeNode<T, FAMILY> = BinaryTreeNodeNested<T>> extends AbstractBinaryTreeNode<T, FAMILY> implements IBinaryTreeNode<T, FAMILY> {
/**
* The function creates a new binary tree node with an optional value and count, and returns it as a specified type.
* @param {BinaryTreeNodeId} id - The `id` parameter is the identifier for the binary tree node. It is of type
* `BinaryTreeNodeId`, which could be a string or a number depending on how you want to identify your nodes.
* @param {T} [val] - The `val` parameter is an optional value that can be assigned to the node. It represents the
* value stored in the node.
* @param {number} [count] - The count parameter is an optional parameter that represents the number of times the value
* appears in the binary tree node.
* @returns a new instance of the BinaryTreeNode class, casted as the FAMILY type.
*/
createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY {
return new BinaryTreeNode<T, FAMILY>(id, val, count) as FAMILY;
}
}
export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode> extends AbstractBinaryTree<N> implements IBinaryTree<N> {

View file

@ -11,19 +11,6 @@ import {BinaryTree, BinaryTreeNode} from './binary-tree';
import {IBST, IBSTNode} from '../interfaces';
export class BSTNode<T = any, FAMILY extends BSTNode<T, FAMILY> = BSTNodeNested<T>> extends BinaryTreeNode<T, FAMILY> implements IBSTNode<T, FAMILY> {
/**
* The function creates a new binary search tree node with the specified id, value, and count.
* @param {BinaryTreeNodeId} id - The id parameter is the identifier for the binary tree node. It is used to uniquely
* identify each node in the tree.
* @param {T} [val] - The "val" parameter represents the value that will be stored in the binary tree node. It is an
* optional parameter, meaning it can be omitted when calling the "createNode" function.
* @param {number} [count] - The `count` parameter represents the number of occurrences of the value in the binary
* search tree node. It is an optional parameter, so it can be omitted when calling the `createNode` method.
* @returns The method is returning a new instance of the BSTNode class, casted as the FAMILY type.
*/
override createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY {
return new BSTNode<T, FAMILY>(id, val, count) as FAMILY;
}
}
export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N> implements IBST<N> {

View file

@ -18,19 +18,6 @@ export class RBTreeNode<T = any, FAMILY extends RBTreeNode<T, FAMILY> = RBTreeNo
this._color = value;
}
/**
* The function creates a new RBTreeNode with the given id, value, and count and returns it as a FAMILY object.
* @param {BinaryTreeNodeId} id - The `id` parameter is the identifier for the binary tree node. It is used to uniquely
* identify each node in the tree.
* @param {T | null} [val] - The "val" parameter represents the value to be stored in the node. It can be of type T
* (generic type) or null.
* @param {number} [count] - The `count` parameter represents the number of occurrences of the value in the binary tree
* node.
* @returns The method is returning a new instance of the RBTreeNode class, casted as a FAMILY type.
*/
override createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY {
return new RBTreeNode(id, val, count) as FAMILY;
}
// private override _parent: RBNode<T> | null;
// override set parent(v: RBNode<T> | null) {

View file

@ -10,19 +10,6 @@ import {ITreeMultiset, ITreeMultisetNode} from '../interfaces';
import {AVLTree, AVLTreeNode} from './avl-tree';
export class TreeMultisetNode<T = any, FAMILY extends TreeMultisetNode<T, FAMILY> = TreeMultisetNodeNested<T>> extends AVLTreeNode<T, FAMILY> implements ITreeMultisetNode<T, FAMILY> {
/**
* The function creates a new node in a binary tree with an optional value and count.
* @param {BinaryTreeNodeId} id - The `id` parameter is the identifier for the binary tree node. It is used to uniquely
* identify each node in the tree.
* @param {T} [val] - The `val` parameter represents the value to be stored in the node. It is an optional parameter,
* meaning it can be omitted when calling the `createNode` method.
* @param {number} [count] - The `count` parameter represents the number of occurrences of the value in the binary tree
* node. It is an optional parameter, so it can be omitted when calling the `createNode` method.
* @returns The method is returning a new instance of the TreeMultisetNode class, casted as the FAMILY type.
*/
override createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY {
return new TreeMultisetNode(id, val, count) as FAMILY;
}
}
/**

View file

@ -13,8 +13,6 @@ import {AbstractBinaryTreeNode} from '../binary-tree';
export interface IAbstractBinaryTreeNode<T, FAMILY extends IAbstractBinaryTreeNode<T, FAMILY>> {
createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY;
get id(): BinaryTreeNodeId
set id(v: BinaryTreeNodeId)
@ -44,10 +42,6 @@ export interface IAbstractBinaryTreeNode<T, FAMILY extends IAbstractBinaryTreeNo
get height(): number
set height(v: number)
swapLocation(swapNode: FAMILY): FAMILY
clone(): FAMILY | null;
}
export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'], N>> {
@ -77,6 +71,8 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
get count(): number
swapLocation(srcNode: N, destNode: N): N
clear(): void
isEmpty(): boolean

View file

@ -3,7 +3,6 @@ import {IBinaryTree, IBinaryTreeNode} from './binary-tree';
import {BinaryTreeDeletedResult, BinaryTreeNodeId, BinaryTreeNodePropertyName} from '../types';
export interface IBSTNode<T, FAMILY extends IBSTNode<T, FAMILY>> extends IBinaryTreeNode<T, FAMILY> {
createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY
}
export interface IBST<N extends BSTNode<N['val'], N>> extends IBinaryTree<N> {

View file

@ -3,7 +3,6 @@ import {IBST, IBSTNode} from './bst';
import {BinaryTreeNodeId} from '../types';
export interface IRBTreeNode<T, FAMILY extends IRBTreeNode<T, FAMILY>> extends IBSTNode<T, FAMILY> {
createNode(id: BinaryTreeNodeId, val?: T, count?: number): FAMILY
}
export interface IRBTree<N extends RBTreeNode<N['val'], N>> extends IBST<N> {