Skip to content

Commit

Permalink
Merge pull request #17 from zrwusa/optimization
Browse files Browse the repository at this point in the history
1. No need for dfsIterative; integrate it directly into the dfs metho…
  • Loading branch information
zrwusa authored Oct 21, 2023
2 parents cb56b04 + a632916 commit 5825d3f
Show file tree
Hide file tree
Showing 30 changed files with 295 additions and 422 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,14 @@ Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.id) // ['A', 'B', 'D
## Code design
### Adhere to ES6 standard naming conventions for APIs.
Standardize API conventions by using 'add' and 'delete' for element manipulation methods in all data structures.
Opt for concise and clear method names, avoiding excessive length while ensuring explicit intent.
### Object-oriented programming(OOP)
By strictly adhering to object-oriented design (BinaryTree -> BST -> AVLTree -> TreeMultiset), you can seamlessly
inherit the existing data structures to implement the customized ones you need. Object-oriented design stands as the
optimal approach to data structure design.
Expand Down
12 changes: 6 additions & 6 deletions src/data-structures/binary-tree/avl-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
}

/**
* The `swapLocation` function swaps the location of two nodes in a binary tree.
* @param {N} srcNode - The source node that you want to swap with the destination node.
* The `_swap` function swaps the location of two nodes in a binary tree.
* @param {N} srcNode - The source node that you want to _swap with the destination node.
* @param {N} destNode - The `destNode` parameter represents the destination node where the values from `srcNode` will
* be swapped to.
* @returns The `destNode` is being returned.
*/
override swapLocation(srcNode: N, destNode: N): N {
protected override _swap(srcNode: N, destNode: N): N {
const {key, val, height} = destNode;
const tempNode = this.createNode(key, val);

Expand Down Expand Up @@ -85,14 +85,14 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
}

/**
* The function overrides the remove method of a binary tree and performs additional operations to balance the tree after
* The function overrides the delete method of a binary tree and performs additional operations to balance the tree after
* deletion.
* @param {BinaryTreeNodeKey} key - The `key` parameter represents the identifier of the binary tree node that needs to be
* removed.
* @returns The method is returning an array of `BinaryTreeDeletedResult<N>` objects.
*/
override remove(key: BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
const deletedResults = super.remove(key);
override delete(key: BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
const deletedResults = super.delete(key);
for (const {needBalanced} of deletedResults) {
if (needBalanced) {
this._balancePath(needBalanced);
Expand Down
293 changes: 79 additions & 214 deletions src/data-structures/binary-tree/binary-tree.ts

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/data-structures/binary-tree/rb-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
// // Remove a node
// private _removeNode(node: N, replacement: N | null | undefined): void {
// if (node === this.root && !replacement) {
// // If there's only the root node and no replacement, simply remove the root node
// // If there's only the root node and no replacement, simply delete the root node
// this._setRoot(null);
// } else if (node === this.root || this._isNodeRed(node)) {
// // If the node is the root or a red node, remove it directly
// // If the node is the root or a red node, delete it directly
// if (node.parent!.left === node) {
// node.parent!.left = replacement;
// } else {
Expand Down Expand Up @@ -205,7 +205,7 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
// node.right = null;
// }
//
// override remove(nodeOrKey: BinaryTreeNodeKey | N): BinaryTreeDeletedResult<N>[] {
// override delete(nodeOrKey: BinaryTreeNodeKey | N): BinaryTreeDeletedResult<N>[] {
// const node = this.get(nodeOrKey);
// const result: BinaryTreeDeletedResult<N>[] = [{deleted: undefined, needBalanced: null}];
// if (!node) return result; // Node does not exist
Expand Down
31 changes: 10 additions & 21 deletions src/data-structures/binary-tree/tree-multiset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset

/**
* The function swaps the location of two nodes in a tree data structure.
* @param {N} srcNode - The source node that we want to swap with the destination node.
* @param {N} srcNode - The source node that we want to _swap with the destination node.
* @param {N} destNode - The `destNode` parameter represents the destination node where the values from `srcNode` will
* be swapped with.
* @returns the `destNode` after swapping its values with the `srcNode`.
*/
override swapLocation(srcNode: N, destNode: N): N {
protected override _swap(srcNode: N, destNode: N): N {
const {key, val, count, height} = destNode;
const tempNode = this.createNode(key, val, count);
if (tempNode) {
Expand Down Expand Up @@ -285,15 +285,15 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
}

/**
* The `remove` function removes a node from a binary search tree and returns the deleted node along with the parent
* The `delete` function removes a node from a binary search tree and returns the deleted node along with the parent
* node that needs to be balanced.
* @param {N | BinaryTreeNodeKey | null} nodeOrKey - The `nodeOrKey` parameter can be one of the following:
* @param {boolean} [ignoreCount] - The `ignoreCount` parameter is an optional boolean parameter that determines
* whether to ignore the count of the node being removed. If `ignoreCount` is set to `true`, the count of the node will
* not be taken into account when removing it. If `ignoreCount` is set to `false
* @returns The function `remove` returns an array of `BinaryTreeDeletedResult<N>` objects.
* @returns The function `delete` returns an array of `BinaryTreeDeletedResult<N>` objects.
*/
override remove(nodeOrKey: N | BinaryTreeNodeKey, ignoreCount = false): BinaryTreeDeletedResult<N>[] {
override delete(nodeOrKey: N | BinaryTreeNodeKey, ignoreCount = false): BinaryTreeDeletedResult<N>[] {
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
if (!this.root) return bstDeletedResult;

Expand Down Expand Up @@ -324,7 +324,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;
if (leftSubTreeRightMost) {
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
orgCurrent = this.swapLocation(curr, leftSubTreeRightMost);
orgCurrent = this._swap(curr, leftSubTreeRightMost);
if (parentOfLeftSubTreeMax) {
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) {
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
Expand Down Expand Up @@ -515,7 +515,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
* @returns The BFSCount() function returns an array of numbers, specifically the count property of each node in the
* bfs traversal.
*/
BFSCount(): number[] {
bfsCount(): number[] {
const nodes = super.bfs('node');
return nodes.map(node => node.count);
}
Expand Down Expand Up @@ -550,23 +550,12 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
* the specified traversal pattern.
* @param {'in' | 'pre' | 'post'} [pattern] - The pattern parameter is a string that specifies the traversal order for
* the Depth-First Search (dfs) algorithm. It can have three possible values: 'in', 'pre', or 'post'.
* @param loopType - The loopType parameter is a string that specifies the type of loop to use when traversing the
* @returns The dfsCountIterative function returns an array of numbers, which represents the count property of each node
* in the dfs traversal.
*/
dfsCountIterative(pattern: DFSOrderPattern = 'in'): number[] {
const nodes = super.dfsIterative(pattern, 'node');
return nodes.map(node => node.count);
}

/**
* The dfsCount function returns an array of counts for each node in a depth-first search traversal.
* @param {DFSOrderPattern} [pattern] - The pattern parameter is an optional parameter that specifies the order in which
* the Depth-First Search (dfs) algorithm should traverse the nodes. It can have one of the following values:
* @returns The dfsCount function returns an array of numbers, specifically the count property of each node in the dfs
* traversal.
*/
dfsCount(pattern: DFSOrderPattern = 'in'): number[] {
const nodes = super.dfs(pattern, 'node');
dfsCount(pattern: DFSOrderPattern = 'in', loopType: LoopType = LoopType.ITERATIVE): number[] {
const nodes = super.dfs(pattern, 'node', loopType);
return nodes.map(node => node.count);
}

Expand Down
2 changes: 1 addition & 1 deletion src/data-structures/hash/hash-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class HashMap<K, V> {
return undefined;
}

remove(key: K): void {
delete(key: K): void {
const index = this._hash(key);
if (!this.table[index]) {
return;
Expand Down
6 changes: 3 additions & 3 deletions src/data-structures/hash/hash-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,13 @@ export class HashTable<K, V> {
}

/**
* The remove function removes a key-value pair from a hash table.
* The delete function removes a key-value pair from a hash table.
* @param {K} key - The `key` parameter represents the key of the key-value pair that needs to be removed from the hash
* table.
* @returns Nothing is being returned. The `remove` method has a return type of `void`, which means it does not return
* @returns Nothing is being returned. The `delete` method has a return type of `void`, which means it does not return
* any value.
*/
remove(key: K): void {
delete(key: K): void {
const index = this._hash(key);
let currentNode = this._buckets[index];
let prevNode: HashTableNode<K, V> | null = null;
Expand Down
7 changes: 5 additions & 2 deletions src/data-structures/heap/heap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ export class FibonacciHeap<E> {
* @protected
* @returns FibonacciHeapNode<E>[] - An array containing the nodes of the linked list.
*/
consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {
consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {
const nodes: FibonacciHeapNode<E>[] = [];
if (!head) return nodes;

Expand Down Expand Up @@ -448,7 +448,10 @@ export class FibonacciHeap<E> {
protected consolidate(): void {
const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this.size);
const nodes = this.consumeLinkedList(this.root);
let x: FibonacciHeapNode<E> | undefined, y: FibonacciHeapNode<E> | undefined, d: number, t: FibonacciHeapNode<E> | undefined;
let x: FibonacciHeapNode<E> | undefined,
y: FibonacciHeapNode<E> | undefined,
d: number,
t: FibonacciHeapNode<E> | undefined;

for (const node of nodes) {
x = node;
Expand Down
6 changes: 3 additions & 3 deletions src/data-structures/linked-list/skip-linked-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ export class SkipList<K, V> {
}

/**
* The `remove` function removes a node with a specific key from a Skip List data structure.
* The `delete` function removes a node with a specific key from a Skip List data structure.
* @param {K} key - The key parameter represents the key of the node that needs to be removed from the skip list.
* @returns The `remove` method returns a boolean value. It returns `true` if the key was successfully removed from the
* @returns The `delete` method returns a boolean value. It returns `true` if the key was successfully removed from the
* skip list, and `false` if the key was not found in the skip list.
*/
remove(key: K): boolean {
delete(key: K): boolean {
const update: SkipListNode<K, V>[] = new Array(this.maxLevel).fill(this.head);
let current = this.head;

Expand Down
4 changes: 2 additions & 2 deletions src/data-structures/queue/deque.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,12 @@ export class ArrayDeque<E> {
}

/**
* The remove function removes an element from an array at a specified index.
* The delete function removes an element from an array at a specified index.
* @param {number} index - The index parameter specifies the position of the element to be removed from the array. It
* is a number that represents the index of the element to be removed.
* @returns The method is returning an array containing the removed element.
*/
remove(index: number) {
delete(index: number) {
return this._nodes.splice(index, 1);
}

Expand Down
2 changes: 1 addition & 1 deletion src/data-structures/queue/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class Queue<E = any> {

if (this.offset * 2 < this.nodes.length) return first;

// only remove dequeued elements when reaching half size
// only delete dequeued elements when reaching half size
// to decrease latency of shifting elements.
this.nodes = this.nodes.slice(this.offset);
this.offset = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/data-structures/trie/trie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ export class Trie {

/**
* Remove a word from the Trie structure.
* @param{string} word - The word to remove.
* @param{string} word - The word to delete.
* @returns {boolean} True if the word was successfully removed.
*/
remove(word: string) {
delete(word: string) {
word = this._caseProcess(word);
let isDeleted = false;
const dfs = (cur: TrieNode, i: number): boolean => {
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/binary-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export interface IBinaryTree<N extends BinaryTreeNode<N['val'], N>> {

add(keyOrNode: BinaryTreeNodeKey | N | null, val?: N['val']): N | null | undefined;

remove(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[];
delete(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[];
}
28 changes: 14 additions & 14 deletions test/unit/data-structures/binary-tree/avl-tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,56 +41,56 @@ describe('AVL Tree Test', () => {
expect(bfs[0].key).toBe(8);
expect(bfs[bfs.length - 1].key).toBe(16);

expect(tree.remove(11)[0].deleted?.key).toBe(11);
expect(tree.delete(11)[0].deleted?.key).toBe(11);
expect(tree.isAVLBalanced()).toBe(true);
expect(node15 && tree.getHeight(node15)).toBe(2);

expect(tree.remove(1)[0].deleted?.key).toBe(1);
expect(tree.delete(1)[0].deleted?.key).toBe(1);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(4);

expect(tree.remove(4)[0].deleted?.key).toBe(4);
expect(tree.delete(4)[0].deleted?.key).toBe(4);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(4);

expect(tree.remove(10)[0].deleted?.key).toBe(10);
expect(tree.delete(10)[0].deleted?.key).toBe(10);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(3);

expect(tree.remove(15)[0].deleted?.key).toBe(15);
expect(tree.delete(15)[0].deleted?.key).toBe(15);
expect(tree.isAVLBalanced()).toBe(true);

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

expect(tree.remove(5)[0].deleted?.key).toBe(5);
expect(tree.delete(5)[0].deleted?.key).toBe(5);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(3);

expect(tree.remove(13)[0].deleted?.key).toBe(13);
expect(tree.delete(13)[0].deleted?.key).toBe(13);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(3);

expect(tree.remove(3)[0].deleted?.key).toBe(3);
expect(tree.delete(3)[0].deleted?.key).toBe(3);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(3);

expect(tree.remove(8)[0].deleted?.key).toBe(8);
expect(tree.delete(8)[0].deleted?.key).toBe(8);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(3);

expect(tree.remove(6)[0].deleted?.key).toBe(6);
expect(tree.remove(6).length).toBe(0);
expect(tree.delete(6)[0].deleted?.key).toBe(6);
expect(tree.delete(6).length).toBe(0);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(2);

expect(tree.remove(7)[0].deleted?.key).toBe(7);
expect(tree.delete(7)[0].deleted?.key).toBe(7);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(2);

expect(tree.remove(9)[0].deleted?.key).toBe(9);
expect(tree.delete(9)[0].deleted?.key).toBe(9);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(2);
expect(tree.remove(14)[0].deleted?.key).toBe(14);
expect(tree.delete(14)[0].deleted?.key).toBe(14);
expect(tree.isAVLBalanced()).toBe(true);
expect(tree.getHeight()).toBe(1);

Expand Down
4 changes: 2 additions & 2 deletions test/unit/data-structures/binary-tree/binary-tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ describe('BinaryTree', () => {
expect(binaryTree.size).toBe(1);
});

test('should remove a node', () => {
test('should delete a node', () => {
const node = binaryTree.add(1);
expect(binaryTree.size).toBe(1);

if (node) {
const result = binaryTree.remove(node);
const result = binaryTree.delete(node);
expect(result).toHaveLength(1);
expect(binaryTree.size).toBe(0);
}
Expand Down
Loading

0 comments on commit 5825d3f

Please sign in to comment.