From 57d29f61e9945abf0b93be65eaf3a43043b52d3c Mon Sep 17 00:00:00 2001
From: anthonycampbell <anthony-campbell@hotmail.com>
Date: Sat, 25 Sep 2021 23:05:27 -0700
Subject: [PATCH 01/22] Adding gale-shapley algorithm

---
 src/js/algorithms/graph/gale-shapley.js | 77 +++++++++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 src/js/algorithms/graph/gale-shapley.js

diff --git a/src/js/algorithms/graph/gale-shapley.js b/src/js/algorithms/graph/gale-shapley.js
new file mode 100644
index 00000000..b0d52689
--- /dev/null
+++ b/src/js/algorithms/graph/gale-shapley.js
@@ -0,0 +1,77 @@
+class Person {
+	constructor(id, gender, ranks, rankIndex, status = "single") {
+		this.id = id
+		this.gender = gender
+		this.ranks = ranks
+		this.i = rankIndex
+		this.status = status
+		this.partner = null
+	}
+}
+
+function galeShapley(proposers, reviewers) {
+	let perfectMatching = new Map()
+	for (let [pid, p] of proposers) {
+		while (p.i < p.ranks.length) {
+			let rid = p.ranks[p.i]
+			let r = reviewers.get(rid)
+			p.i++
+			if (r.status === "single") {
+				r.status = "engaged"
+				r.partner = p
+				p.partner = r
+				perfectMatching.set(pid, rid)
+				proposers.delete(pid)
+				break
+			} else if (r.status === "engaged" && r.ranks.get(pid) < r.ranks.get(r.partner.id)) {
+				perfectMatching.delete(r.partner.id)
+				proposers.set(r.partner.id, r.partner)
+				proposers.delete(pid)
+				r.partner.partner = null
+				r.partner = p
+				p.partner = r
+				perfectMatching.set(pid, rid)
+				break
+			}
+		}
+	}
+	return perfectMatching
+}
+
+let men = new Map()
+let women = new Map()
+//O(n^2)
+function createPeople(n, gender, set) {
+	for (let i = 0; i < n; i++) {
+		let id = i
+		let rankIndex = 0
+		let g = gender
+		let ranks = new Array(n)
+		let p
+		for (let i = 0; i < n; i++) ranks[i] = i
+		shuffle(ranks)
+		if (gender == 'w') {
+			let wRanks = new Map()
+			for (let i = 0; i < n; i++) wRanks.set(i, ranks[i])
+			p = new Person(id, g, wRanks, null)
+		} else {
+			p = new Person(id, g, ranks, rankIndex)
+		}
+		set.set(i, p)
+	}
+}
+
+//fisher-yates shuffle O(n)
+function shuffle(array) {
+	for (let i = array.length - 1; i >= 0; i--) {
+		let j = Math.floor(Math.random() * (i + 1))
+		let temp = array[i]
+		array[i] = array[j]
+		array[j] = temp
+	}
+}
+
+createPeople(4, 'm', men)
+createPeople(4, 'w', women)
+let stableMatching = galeShapley(men, women)
+console.log(stableMatching)

From 4fb2b45fbf4dd2db92f3ad2c278055cf4c4fe735 Mon Sep 17 00:00:00 2001
From: Jeff Zhang <72734421+jeff-zhenz@users.noreply.github.com>
Date: Wed, 11 May 2022 21:44:56 +0800
Subject: [PATCH 02/22] fix: CircularLinkedList insert function

---
 src/js/data-structures/circular-linked-list.js | 2 +-
 src/ts/data-structures/circular-linked-list.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/js/data-structures/circular-linked-list.js b/src/js/data-structures/circular-linked-list.js
index 4209087a..865fcb70 100644
--- a/src/js/data-structures/circular-linked-list.js
+++ b/src/js/data-structures/circular-linked-list.js
@@ -32,7 +32,7 @@ export default class CircularLinkedList extends LinkedList {
           node.next = this.head;
         } else {
           node.next = current;
-          current = this.getElementAt(this.size());
+          current = this.getElementAt(this.size() - 1);
           // update last element
           this.head = node;
           current.next = this.head;
diff --git a/src/ts/data-structures/circular-linked-list.ts b/src/ts/data-structures/circular-linked-list.ts
index f422d276..802f6138 100644
--- a/src/ts/data-structures/circular-linked-list.ts
+++ b/src/ts/data-structures/circular-linked-list.ts
@@ -36,7 +36,7 @@ export default class CircularLinkedList<T> extends LinkedList<T> {
           node.next = this.head;
         } else {
           node.next = current;
-          current = this.getElementAt(this.size());
+          current = this.getElementAt(this.size() - 1);
           // update last element
           this.head = node;
           current.next = this.head;

From 91887bc2d54de67cb8a0ed1f6e70ded4d56015ea Mon Sep 17 00:00:00 2001
From: Jeff Zhang <72734421+jeff-zhenz@users.noreply.github.com>
Date: Thu, 12 May 2022 07:52:56 +0800
Subject: [PATCH 03/22] improvements: isSubsetOf function of Set

---
 src/js/data-structures/set.js | 14 ++------------
 src/ts/data-structures/set.ts | 16 ++--------------
 2 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/src/js/data-structures/set.js b/src/js/data-structures/set.js
index 0dc29a0c..996316ac 100644
--- a/src/js/data-structures/set.js
+++ b/src/js/data-structures/set.js
@@ -63,18 +63,8 @@ export default class Set {
   }
 
   isSubsetOf(otherSet) {
-    if (this.size() > otherSet.size()) {
-      return false;
-    }
-    let isSubset = true;
-    this.values().every(value => {
-      if (!otherSet.has(value)) {
-        isSubset = false;
-        return false;
-      }
-      return true;
-    });
-    return isSubset;
+    const values = this.values();
+    return values.every((value) => otherSet.has(value));
   }
 
   isEmpty() {
diff --git a/src/ts/data-structures/set.ts b/src/ts/data-structures/set.ts
index c67faf75..a6d37373 100644
--- a/src/ts/data-structures/set.ts
+++ b/src/ts/data-structures/set.ts
@@ -75,20 +75,8 @@ export default class Set<T> {
   }
 
   isSubsetOf(otherSet: Set<T>) {
-    if (this.size() > otherSet.size()) {
-      return false;
-    }
-
-    let isSubset = true;
-    this.values().every(value => {
-      if (!otherSet.has(value)) {
-        isSubset = false;
-        return false;
-      }
-      return true;
-    });
-
-    return isSubset;
+    const values = this.values();
+    return values.every((value) => otherSet.has(value));
   }
 
   isEmpty() {

From f0fa8e52646200cb026831aefcf0390dcae41a26 Mon Sep 17 00:00:00 2001
From: Jeff Zhang <72734421+jeff-zhenz@users.noreply.github.com>
Date: Tue, 17 May 2022 18:16:35 +0800
Subject: [PATCH 04/22] fix: AVL tree insertNode and removeNode functions

---
 src/js/data-structures/avl-tree.js |  45 +++++-------
 src/ts/data-structures/avl-tree.ts | 108 +++++++++--------------------
 2 files changed, 53 insertions(+), 100 deletions(-)

diff --git a/src/js/data-structures/avl-tree.js b/src/js/data-structures/avl-tree.js
index 8ea3cfb9..6b4ee7c0 100644
--- a/src/js/data-structures/avl-tree.js
+++ b/src/js/data-structures/avl-tree.js
@@ -101,13 +101,13 @@ export default class AVLTree extends BinarySearchTree {
   insertNode(node, key) {
     if (node == null) {
       return new Node(key);
-    } if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
+    }
+    if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
       node.left = this.insertNode(node.left, key);
-    } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
-      node.right = this.insertNode(node.right, key);
     } else {
-      return node; // duplicated key
+      node.right = this.insertNode(node.right, key);
     }
+
     // verify if tree is balanced
     const balanceFactor = this.getBalanceFactor(node);
     if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
@@ -116,7 +116,7 @@ export default class AVLTree extends BinarySearchTree {
         node = this.rotationLL(node);
       } else {
         // Left right case
-        return this.rotationLR(node);
+        node = this.rotationLR(node);
       }
     }
     if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
@@ -125,7 +125,7 @@ export default class AVLTree extends BinarySearchTree {
         node = this.rotationRR(node);
       } else {
         // Right left case
-        return this.rotationRL(node);
+        node = this.rotationRL(node);
       }
     }
     return node;
@@ -136,32 +136,25 @@ export default class AVLTree extends BinarySearchTree {
     if (node == null) {
       return node;
     }
+
     // verify if tree is balanced
     const balanceFactor = this.getBalanceFactor(node);
     if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
-      // Left left case
-      if (
-        this.getBalanceFactor(node.left) === BalanceFactor.BALANCED
-        || this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT
-      ) {
-        return this.rotationLL(node);
-      }
-      // Left right case
-      if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {
-        return this.rotationLR(node.left);
+      if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
+        // Left left case
+        node = this.rotationLL(node);
+      } else {
+        // Left right case
+        node = this.rotationLR(node);
       }
     }
     if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
-      // Right right case
-      if (
-        this.getBalanceFactor(node.right) === BalanceFactor.BALANCED
-        || this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT
-      ) {
-        return this.rotationRR(node);
-      }
-      // Right left case
-      if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {
-        return this.rotationRL(node.right);
+      if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
+        // Right right case
+        node = this.rotationRR(node);
+      } else {
+        // Right left case
+        node = this.rotationRL(node);
       }
     }
     return node;
diff --git a/src/ts/data-structures/avl-tree.ts b/src/ts/data-structures/avl-tree.ts
index feb44a19..266e204a 100644
--- a/src/ts/data-structures/avl-tree.ts
+++ b/src/ts/data-structures/avl-tree.ts
@@ -100,102 +100,62 @@ export default class AVLTree<T> extends BinarySearchTree<T> {
   protected insertNode(node: Node<T>, key: T) {
     if (node == null) {
       return new Node(key);
-    } else if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
+    }
+    if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
       node.left = this.insertNode(node.left, key);
-    } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
-      node.right = this.insertNode(node.right, key);
     } else {
-      return node; // duplicated key
+      node.right = this.insertNode(node.right, key);
     }
 
     // verify if tree is balanced
-    const balanceState = this.getBalanceFactor(node);
-
-    if (balanceState === BalanceFactor.UNBALANCED_LEFT) {
+    const balanceFactor = this.getBalanceFactor(node);
+    if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
       if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
         // Left left case
         node = this.rotationLL(node);
       } else {
         // Left right case
-        return this.rotationLR(node);
+        node = this.rotationLR(node);
       }
     }
-
-    if (balanceState === BalanceFactor.UNBALANCED_RIGHT) {
+    if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
       if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
         // Right right case
         node = this.rotationRR(node);
       } else {
         // Right left case
-        return this.rotationRL(node);
+        node = this.rotationRL(node);
       }
     }
-
     return node;
   }
 
   protected removeNode(node: Node<T>, key: T) {
-    if (node == null) {
-      return null;
-    }
-
-    if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
-      // The key to be deleted is in the left sub-tree
-      node.left = this.removeNode(node.left, key);
-    } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
-      // The key to be deleted is in the right sub-tree
-      node.right = this.removeNode(node.right, key);
-    } else {
-      // node is the node to be deleted
-      if (node.left == null && node.right == null) {
-        node = null;
-      } else if (node.left == null && node.right != null) {
-        node = node.right;
-      } else if (node.left != null && node.right == null) {
-        node = node.left;
-      } else {
-        // node has 2 children, get the in-order successor
-        const inOrderSuccessor = this.minNode(node.right);
-        node.key = inOrderSuccessor.key;
-        node.right = this.removeNode(node.right, inOrderSuccessor.key);
-      }
-    }
-
-    if (node == null) {
-      return node;
-    }
-
-    // verify if tree is balanced
-    const balanceState = this.getBalanceFactor(node);
-
-    if (balanceState === BalanceFactor.UNBALANCED_LEFT) {
-      // Left left case
-      if (
-        this.getBalanceFactor(node.left) === BalanceFactor.BALANCED ||
-        this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT
-      ) {
-        return this.rotationLL(node);
-      }
-      // Left right case
-      if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {
-        return this.rotationLR(node.left);
-      }
-    }
-
-    if (balanceState === BalanceFactor.UNBALANCED_RIGHT) {
-      // Right right case
-      if (
-        this.getBalanceFactor(node.right) === BalanceFactor.BALANCED ||
-        this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT
-      ) {
-        return this.rotationRR(node);
-      }
-      // Right left case
-      if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {
-        return this.rotationRL(node.right);
-      }
-    }
-
-    return node;
+   node = super.removeNode(node, key); // {1}
+   if (node == null) {
+     return node;
+   }
+
+   // verify if tree is balanced
+   const balanceFactor = this.getBalanceFactor(node);
+   if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
+     if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
+       // Left left case
+       node = this.rotationLL(node);
+     } else {
+       // Left right case
+       node = this.rotationLR(node);
+     }
+   }
+   if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
+     if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
+       // Right right case
+       node = this.rotationRR(node);
+     } else {
+       // Right left case
+       node = this.rotationRL(node);
+     }
+   }
+   return node;
   }
 }

From d079c26c6c229e91f796556521b723bd954925a5 Mon Sep 17 00:00:00 2001
From: NMTuan <tuancn8k63uet@gmail.com>
Date: Mon, 23 May 2022 03:23:17 +0700
Subject: [PATCH 05/22] BinarySearchMCCTesting

BinarySearchMCCTesting
---
 test/js/algorithms/search/binary-search.spec.js | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/test/js/algorithms/search/binary-search.spec.js b/test/js/algorithms/search/binary-search.spec.js
index 220c1b28..4e4014ce 100644
--- a/test/js/algorithms/search/binary-search.spec.js
+++ b/test/js/algorithms/search/binary-search.spec.js
@@ -1,4 +1,20 @@
+import { expect } from 'chai';
 import { binarySearch } from '../../../../src/js/index';
 import { testSearchAlgorithm } from './search-algorithms-tests';
 
 testSearchAlgorithm(binarySearch, 'Binary Search');
+
+describe('binarySearch', () => {
+  it('search elements in array of numbers', () => {
+    expect(binarySearch([0, 5, 3], 1)).to.equal(-1);
+    expect(binarySearch([2, 64, 33, 40, 100], 40)).to.equal(2);
+    expect(binarySearch([1, 2], 2)).to.equal(1);
+    expect(binarySearch([10, 20, 15, 40, 65], 40)).to.equal(3);
+    expect(binarySearch([1, 6, 7, 8, 12, 13, 14, 19, 21, 23, 24, 24, 24, 300], 24)).to.equal(10);
+    expect(binarySearch([1, 2, 3, 610, 800, 1250, 1360, 1400, 1905], 600)).to.equal(-1);
+    expect(binarySearch([1, 2, 3, 742, 800, 1250, 1360, 1400, 19550], 2)).to.equal(1);
+    expect(binarySearch([1, 2, 3, 743, 800, 1000, 1335, 1490, 1800], 743)).to.equal(3);
+    expect(binarySearch([1, 2, 3, 700, 800, 1233, 1380, 1400, 19678], 800)).to.equal(4);
+    expect(binarySearch([0, 10, 11, 12, 13, 14, 15], 10)).to.equal(1);
+  });
+});

From 39a439d09caa8295487cc5903601bca894fa0f3c Mon Sep 17 00:00:00 2001
From: VictorAugDB <vdbernardes@gmail.com>
Date: Wed, 25 May 2022 11:10:09 -0300
Subject: [PATCH 06/22] Change URL path where application is running to debug

The URL must be http://127.0.0.1:8080/examples instead of http://127.0.0.1:8887/examples
---
 .vscode/launch.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8b53d61d..85c3207b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -8,7 +8,7 @@
         "type": "chrome",
         "request": "launch",
         "name": "Chrome",
-        "url": "http://127.0.0.1:8887/examples",
+        "url": "http://127.0.0.1:8080/examples",
         "webRoot": "${workspaceRoot}"
       },
       {

From 5c21cead6bb1e2ec83e239b5662aee3d05f1ec5e Mon Sep 17 00:00:00 2001
From: VictorAugDB <vdbernardes@gmail.com>
Date: Thu, 26 May 2022 15:58:36 -0300
Subject: [PATCH 07/22] run http-server without cache

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index d0ec6c91..db66f5b6 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
     "generate-report2": "nyc --report-dir coverage npm run test",
     "go": "npm run clean && npm run lint && npm run build && npm run test",
     "webpack": "webpack --env build",
-    "serve": "http-server"
+    "serve": "http-server -c-1"
   },
   "nyc": {
     "include": [

From 2904130ea5ed741a4432198219faede6a6282397 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 30 May 2022 19:39:42 +0000
Subject: [PATCH 08/22] Bump node-fetch from 2.6.1 to 2.6.7

Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7.
- [Release notes](https://github.com/node-fetch/node-fetch/releases)
- [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7)

---
updated-dependencies:
- dependency-name: node-fetch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 package-lock.json | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 3eefb3e9..0182e367 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5215,10 +5215,13 @@
       "dev": true
     },
     "node-fetch": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
-      "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
-      "dev": true
+      "version": "2.6.7",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+      "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+      "dev": true,
+      "requires": {
+        "whatwg-url": "^5.0.0"
+      }
     },
     "node-libs-browser": {
       "version": "2.2.1",
@@ -9648,6 +9651,12 @@
         }
       }
     },
+    "tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
+      "dev": true
+    },
     "trim-right": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
@@ -10601,6 +10610,12 @@
         }
       }
     },
+    "webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
+      "dev": true
+    },
     "webpack": {
       "version": "4.44.2",
       "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
@@ -11105,6 +11120,16 @@
         }
       }
     },
+    "whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+      "dev": true,
+      "requires": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",

From f1ff66f48b07b27544f5f0030df706b1c621d0f2 Mon Sep 17 00:00:00 2001
From: Sojin <77185816+SojinSamuel@users.noreply.github.com>
Date: Tue, 2 Aug 2022 16:48:25 +0530
Subject: [PATCH 09/22] Found Typographical Error in Documentation

Typos Found directoty, depencies, nagivate. Found Literal errors were updated.
---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index df8c3da9..96845564 100644
--- a/README.md
+++ b/README.md
@@ -61,8 +61,8 @@ Source code of **Learning JavaScript Data Structures and Algorithms** book, thir
 ## Installing and running the book examples With Node
 
 * Install [Node](https://nodejs.org)
-* Open terminal/cmd and change directoty to this project folder: `cd /Users/.../javascript-datastructures-algorithms` (Linux/Max) or `cd C:/.../javascript-datastructures-algorithms`
-* run `npm install` to install all depencies
+* Open terminal/cmd and change directory to this project folder: `cd /Users/.../javascript-datastructures-algorithms` (Linux/Max) or `cd C:/.../javascript-datastructures-algorithms`
+* run `npm install` to install all dependencies
 * To see the examples, run `http-server html` or `npm run serve`. Open your browser `http:\\localhost:8080` to see the book examples
 * Or `cd html/chapter01` and run each javascript file with node: `node 02-Variables`
 
@@ -70,7 +70,7 @@ Source code of **Learning JavaScript Data Structures and Algorithms** book, thir
 
 * Right click on the html file you would like to see the examples, right click and 'Open with Chrome (or any other browser)'
 
-* Or open the `examples/index.html` file to easily nagivate through all examples:
+* Or open the `examples/index.html` file to easily navigate through all examples:
 
 * Demo: [https://javascript-ds-algorithms-book.firebaseapp.com](https://javascript-ds-algorithms-book.firebaseapp.com)
 

From a9ba9d84b3798deab8a93d6851852348b0ad2368 Mon Sep 17 00:00:00 2001
From: Yamiqu <klingonslaw@hotmail.com>
Date: Thu, 4 Aug 2022 01:46:07 +0800
Subject: [PATCH 10/22] fix: hash-table-linear-probing get function

---
 src/js/data-structures/hash-table-linear-probing.js | 2 +-
 src/ts/data-structures/hash-table-linear-probing.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/js/data-structures/hash-table-linear-probing.js b/src/js/data-structures/hash-table-linear-probing.js
index 2b7af8b2..73f70374 100644
--- a/src/js/data-structures/hash-table-linear-probing.js
+++ b/src/js/data-structures/hash-table-linear-probing.js
@@ -51,7 +51,7 @@ export default class HashTableLinearProbing {
         index++;
       }
       if (this.table[index] != null && this.table[index].key === key) {
-        return this.table[position].value;
+        return this.table[index].value;
       }
     }
     return undefined;
diff --git a/src/ts/data-structures/hash-table-linear-probing.ts b/src/ts/data-structures/hash-table-linear-probing.ts
index 872b4421..fb82d20a 100644
--- a/src/ts/data-structures/hash-table-linear-probing.ts
+++ b/src/ts/data-structures/hash-table-linear-probing.ts
@@ -54,7 +54,7 @@ export default class HashTableLinearProbing<K, V> {
         index++;
       }
       if (this.table[index] != null && this.table[index].key === key) {
-        return this.table[position].value;
+        return this.table[index].value;
       }
     }
     return undefined;

From 0da564facd6edd6c0508e0232fda50cdc34a9a75 Mon Sep 17 00:00:00 2001
From: Lin Jinzhang <jinzhanglin@hotmail.com>
Date: Sun, 21 Aug 2022 00:09:31 +0800
Subject: [PATCH 11/22] fix: remove useless argument

---
 examples/chapter09/04-Fibonacci.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/chapter09/04-Fibonacci.js b/examples/chapter09/04-Fibonacci.js
index 3b395774..67eae205 100644
--- a/examples/chapter09/04-Fibonacci.js
+++ b/examples/chapter09/04-Fibonacci.js
@@ -30,7 +30,7 @@ function fibonacciMemoization(n) {
   const memo = [0, 1];
   const fibonacci = (n) => {
     if (memo[n] != null) return memo[n];
-    return memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);
+    return memo[n] = fibonacci(n - 1) + fibonacci(n - 2);
   };
   return fibonacci(n);
 }

From 83958762e47fc6d89d870eced0ed83e48253ccae Mon Sep 17 00:00:00 2001
From: bolsonitro <bolsonitro_bitcoiner@protonmail.com>
Date: Sun, 4 Dec 2022 15:31:13 -0300
Subject: [PATCH 12/22] Change line endings to LF in github

---
 .gitattributes | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 .gitattributes

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..cdaaeff1
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,40 @@
+# Handle line endings automatically for files detected as text
+# and leave all files detected as binary untouched.
+* text=auto
+
+#
+# The above will handle all files NOT found below
+#
+# These files are text and should be normalized (Convert crlf => lf)
+*.css           eol=lf
+*.df            eol=lf
+*.htm           eol=lf
+*.html          eol=lf
+*.java          eol=lf
+*.js            eol=lf
+*.json          eol=lf
+*.jsp           eol=lf
+*.jspf          eol=lf
+*.jspx          eol=lf
+*.properties    eol=lf
+*.sh            eol=lf
+*.tld           eol=lf
+*.txt           eol=lf
+*.tag           eol=lf
+*.tagx          eol=lf
+*.xml           eol=lf
+*.yml           eol=lf
+
+# These files are binary and should be left untouched
+# (binary is a macro for -text -diff)
+*.class         binary
+*.dll           binary
+*.ear           binary
+*.gif           binary
+*.ico           binary
+*.jar           binary
+*.jpg           binary
+*.jpeg          binary
+*.png           binary
+*.so            binary
+*.war           binary

From 29031f0bacc6496407d7bdde31c494a4952d5db0 Mon Sep 17 00:00:00 2001
From: Fernanda Freitas <idea.fernanda@gmail.com>
Date: Mon, 10 Apr 2023 10:17:26 -0300
Subject: [PATCH 13/22] Specified the value of 'false' and 'age' within the
 comment

---
 examples/chapter01_02/04-TruthyFalsy.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/chapter01_02/04-TruthyFalsy.js b/examples/chapter01_02/04-TruthyFalsy.js
index c64fa3e1..0090ee74 100644
--- a/examples/chapter01_02/04-TruthyFalsy.js
+++ b/examples/chapter01_02/04-TruthyFalsy.js
@@ -24,4 +24,4 @@ testTruthy({}); // true (object is always true)
 var obj = { name: 'John' };
 testTruthy(obj); // true
 testTruthy(obj.name); // true
-testTruthy(obj.age); // age (property does not exist)
+testTruthy(obj.age); // false (property age does not exist)

From eef66c91d347ee17ac5c935627ffa4029cdf3559 Mon Sep 17 00:00:00 2001
From: Oussama Moussaoui <omoussaoui1337@gmail.com>
Date: Sat, 9 Dec 2023 14:51:29 +0100
Subject: [PATCH 14/22] fix & optimize gcd function

- handle gcd of negative numbers
- fix the case when one of the numbers is equal to zero, gcd(0, x) = absolute value of x
- optimize using modulo instead of repeated subtractions
---
 src/ts/algorithms/math/gcd.ts | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/ts/algorithms/math/gcd.ts b/src/ts/algorithms/math/gcd.ts
index 35818deb..02a6fbbc 100644
--- a/src/ts/algorithms/math/gcd.ts
+++ b/src/ts/algorithms/math/gcd.ts
@@ -1,14 +1,17 @@
 export const gcd = (num1: number, num2: number): number => {
-  if (num1 === 0 || num2 === 0) {
-    return 0;
+  if (num1 < 0 || num2 < 0) {
+    return gcd(Math.abs(num1), Math.abs(num2));
   }
-  if (num1 === num2) {
+  if (num1 === 0) {
+    return num2;
+  }
+  if (num2 === 0) {
     return num1;
   }
   if (num1 > num2) {
-    return gcd(num1 - num2, num2);
+    return gcd(num1 % num2, num2);
   }
-  return gcd(num1, num2 - num1);
+  return gcd(num1, num2 % num1);
 };
 
 export const gcdArray = (num: number[]) => {

From adaaaf4122a891c3b26f670e09cb593d7491eecd Mon Sep 17 00:00:00 2001
From: Oussama Moussaoui <omoussaoui1337@gmail.com>
Date: Sat, 9 Dec 2023 15:02:56 +0100
Subject: [PATCH 15/22] update unit tests for gcd function

- add more tests to cover edge cases and different scenarios
- delete incorrect test (gcd(1, 0) = 0)
---
 test/ts/algorithms/math/gcd.spec.ts | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/test/ts/algorithms/math/gcd.spec.ts b/test/ts/algorithms/math/gcd.spec.ts
index fd565a33..75a66ae6 100644
--- a/test/ts/algorithms/math/gcd.spec.ts
+++ b/test/ts/algorithms/math/gcd.spec.ts
@@ -3,14 +3,26 @@ import { expect } from 'chai';
 import { gcd } from '../../../../src/ts/index';
 
 describe('GCD', () => {
+  it('returns the correct GCD for positive numbers', () => {
+    expect(gcd(8, 12)).to.equal(4);
+    expect(gcd(15, 25)).to.equal(5);
+    expect(gcd(21, 28)).to.equal(7);
+  });
+
+  it('returns the correct GCD for negative numbers', () => {
+    expect(gcd(-8, 12)).to.equal(4);
+    expect(gcd(15, -25)).to.equal(5);
+    expect(gcd(-21, -28)).to.equal(7);
+  });
 
-  it('returns the gcd between two numbers', () => {
+  it('returns the correct GCD when one of the numbers is 0', () => {
+    expect(gcd(0, -12)).to.equal(12);
+    expect(gcd(15, 0)).to.equal(15);
+  });
 
-    expect(gcd(1, 0)).to.equal(0);
-    expect(gcd(1, 1)).to.equal(1);
-    expect(gcd(2, 2)).to.equal(2);
-    expect(gcd(2, 4)).to.equal(2);
-    expect(gcd(2, 3)).to.equal(1);
-    expect(gcd(10, 1000)).to.equal(10);
+  it('returns 1 for co-prime numbers', () => {
+    expect(gcd(7, 22)).to.equal(1);
+    expect(gcd(11, 28)).to.equal(1);
+    expect(gcd(9, 16)).to.equal(1);
   });
 });

From 60e526994daf1c5d7e2c21fada8bd6b9f13d4faa Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 9 Jan 2024 01:42:18 +0000
Subject: [PATCH 16/22] Bump follow-redirects from 1.13.0 to 1.15.4

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.13.0 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.13.0...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 package-lock.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 0182e367..172fd2b4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3444,9 +3444,9 @@
       }
     },
     "follow-redirects": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
-      "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
+      "version": "1.15.4",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+      "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
     },
     "for-in": {
       "version": "1.0.2",

From cc1ce5de1a90395f4161c0442a67f588ac5a34d5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 27 Feb 2024 22:14:58 +0000
Subject: [PATCH 17/22] Bump browserify-sign from 4.2.1 to 4.2.2

Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2.
- [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: browserify-sign
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 package-lock.json | 69 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 51 insertions(+), 18 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 172fd2b4..7cc1b011 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1500,12 +1500,6 @@
       "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
       "dev": true
     },
-    "bn.js": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
-      "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
-      "dev": true
-    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1596,26 +1590,65 @@
       }
     },
     "browserify-sign": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
-      "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz",
+      "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==",
       "dev": true,
       "requires": {
-        "bn.js": "^5.1.1",
-        "browserify-rsa": "^4.0.1",
+        "bn.js": "^5.2.1",
+        "browserify-rsa": "^4.1.0",
         "create-hash": "^1.2.0",
         "create-hmac": "^1.1.7",
-        "elliptic": "^6.5.3",
+        "elliptic": "^6.5.4",
         "inherits": "^2.0.4",
-        "parse-asn1": "^5.1.5",
-        "readable-stream": "^3.6.0",
-        "safe-buffer": "^5.2.0"
+        "parse-asn1": "^5.1.6",
+        "readable-stream": "^3.6.2",
+        "safe-buffer": "^5.2.1"
       },
       "dependencies": {
+        "bn.js": {
+          "version": "5.2.1",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+          "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+          "dev": true
+        },
+        "browserify-rsa": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+          "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
+          "dev": true,
+          "requires": {
+            "bn.js": "^5.0.0",
+            "randombytes": "^2.0.1"
+          }
+        },
+        "elliptic": {
+          "version": "6.5.4",
+          "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+          "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+          "dev": true,
+          "requires": {
+            "bn.js": "^4.11.9",
+            "brorand": "^1.1.0",
+            "hash.js": "^1.0.0",
+            "hmac-drbg": "^1.0.1",
+            "inherits": "^2.0.4",
+            "minimalistic-assert": "^1.0.1",
+            "minimalistic-crypto-utils": "^1.0.1"
+          },
+          "dependencies": {
+            "bn.js": {
+              "version": "4.12.0",
+              "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+              "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+              "dev": true
+            }
+          }
+        },
         "readable-stream": {
-          "version": "3.6.0",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
-          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "version": "3.6.2",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
           "dev": true,
           "requires": {
             "inherits": "^2.0.3",

From 084212758c3cb25929221e23c59ef1369c85fc9f Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 27 Feb 2024 22:15:01 +0000
Subject: [PATCH 18/22] Bump @babel/traverse from 7.12.1 to 7.23.9

Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.12.1 to 7.23.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.9/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 package-lock.json | 294 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 227 insertions(+), 67 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 172fd2b4..0619de3b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,53 +13,51 @@
         "@babel/highlight": "^7.10.4"
       }
     },
-    "@babel/generator": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz",
-      "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==",
+    "@babel/helper-environment-visitor": {
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+      "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+      "dev": true
+    },
+    "@babel/helper-hoist-variables": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+      "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.1",
-        "jsesc": "^2.5.1",
-        "source-map": "^0.5.0"
+        "@babel/types": "^7.22.5"
       },
       "dependencies": {
-        "jsesc": {
-          "version": "2.5.2",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+        "@babel/helper-validator-identifier": {
+          "version": "7.22.20",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+          "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+          "dev": true
+        },
+        "@babel/types": {
+          "version": "7.23.9",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz",
+          "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-string-parser": "^7.23.4",
+            "@babel/helper-validator-identifier": "^7.22.20",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
+        "to-fast-properties": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+          "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
           "dev": true
         }
       }
     },
-    "@babel/helper-function-name": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
-      "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-get-function-arity": "^7.10.4",
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.4"
-      }
-    },
-    "@babel/helper-get-function-arity": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
-      "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.10.4"
-      }
-    },
-    "@babel/helper-split-export-declaration": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
-      "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.11.0"
-      }
+    "@babel/helper-string-parser": {
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
+      "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+      "dev": true
     },
     "@babel/helper-validator-identifier": {
       "version": "7.10.4",
@@ -121,38 +119,134 @@
       "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==",
       "dev": true
     },
-    "@babel/template": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-      "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/parser": "^7.10.4",
-        "@babel/types": "^7.10.4"
-      }
-    },
     "@babel/traverse": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz",
-      "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.12.1",
-        "@babel/helper-function-name": "^7.10.4",
-        "@babel/helper-split-export-declaration": "^7.11.0",
-        "@babel/parser": "^7.12.1",
-        "@babel/types": "^7.12.1",
-        "debug": "^4.1.0",
-        "globals": "^11.1.0",
-        "lodash": "^4.17.19"
+      "version": "7.23.9",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz",
+      "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.6",
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-function-name": "^7.23.0",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/parser": "^7.23.9",
+        "@babel/types": "^7.23.9",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
       },
       "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.23.5",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
+          "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.23.4",
+            "chalk": "^2.4.2"
+          }
+        },
+        "@babel/generator": {
+          "version": "7.23.6",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz",
+          "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.23.6",
+            "@jridgewell/gen-mapping": "^0.3.2",
+            "@jridgewell/trace-mapping": "^0.3.17",
+            "jsesc": "^2.5.1"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.23.0",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+          "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+          "dev": true,
+          "requires": {
+            "@babel/template": "^7.22.15",
+            "@babel/types": "^7.23.0"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.22.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+          "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.22.5"
+          }
+        },
+        "@babel/helper-validator-identifier": {
+          "version": "7.22.20",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+          "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+          "dev": true
+        },
+        "@babel/highlight": {
+          "version": "7.23.4",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
+          "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.22.20",
+            "chalk": "^2.4.2",
+            "js-tokens": "^4.0.0"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.23.9",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz",
+          "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==",
+          "dev": true
+        },
+        "@babel/template": {
+          "version": "7.23.9",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz",
+          "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.23.5",
+            "@babel/parser": "^7.23.9",
+            "@babel/types": "^7.23.9"
+          }
+        },
+        "@babel/types": {
+          "version": "7.23.9",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz",
+          "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-string-parser": "^7.23.4",
+            "@babel/helper-validator-identifier": "^7.22.20",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
+        "ansi-styles": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
         "debug": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
-          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
@@ -163,6 +257,33 @@
           "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
           "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
           "dev": true
+        },
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "dev": true
+        },
+        "jsesc": {
+          "version": "2.5.2",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        },
+        "to-fast-properties": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+          "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+          "dev": true
         }
       }
     },
@@ -185,6 +306,45 @@
         }
       }
     },
+    "@jridgewell/gen-mapping": {
+      "version": "0.3.4",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz",
+      "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==",
+      "dev": true,
+      "requires": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "dev": true
+    },
+    "@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "dev": true
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "dev": true
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.23",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz",
+      "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==",
+      "dev": true,
+      "requires": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
     "@tootallnate/once": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",

From dcf995f74f7494c2cf5241db0ad0a66601b2d998 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 27 Feb 2024 22:15:25 +0000
Subject: [PATCH 19/22] Bump async from 2.6.3 to 2.6.4

Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 package-lock.json | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 172fd2b4..3cee72e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -645,9 +645,9 @@
       "dev": true
     },
     "async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
       "requires": {
         "lodash": "^4.17.14"
       }
@@ -4373,7 +4373,7 @@
         "async": {
           "version": "1.5.2",
           "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+          "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
           "dev": true
         }
       }
@@ -5410,10 +5410,6 @@
           "bundled": true,
           "dev": true
         },
-        "async": {
-          "version": "1.5.2",
-          "bundled": true
-        },
         "atob": {
           "version": "2.1.1",
           "bundled": true,

From fa69786b3832a2956c9634d7f0e2913d1b323ffe Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 16 Mar 2024 23:28:45 +0000
Subject: [PATCH 20/22] Bump follow-redirects from 1.15.4 to 1.15.6

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 package-lock.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 03715898..afb891a9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3637,9 +3637,9 @@
       }
     },
     "follow-redirects": {
-      "version": "1.15.4",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
-      "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
+      "version": "1.15.6",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+      "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
     },
     "for-in": {
       "version": "1.0.2",

From ff6e72c6b25d0c300690301e8f43e693c46c4af7 Mon Sep 17 00:00:00 2001
From: Loiane Groner <loianeg@gmail.com>
Date: Sun, 27 Oct 2024 09:54:41 -0400
Subject: [PATCH 21/22] Create build.yml

---
 .github/workflows/build.yml | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 .github/workflows/build.yml

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 00000000..af297e37
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,27 @@
+# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
+
+name: Node.js CI
+
+on:
+  push:
+    branches: [ "fourth-edition" ]
+  pull_request:
+    branches: [ "fourth-edition" ]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix:
+        node-version: [20.x, 22.x]
+    steps:
+    - uses: actions/checkout@v4
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v4
+      with:
+        node-version: ${{ matrix.node-version }}
+        cache: 'npm'
+    - run: npm test

From 9f4b32178452daa349c0f21c8a3db7e8412d2db9 Mon Sep 17 00:00:00 2001
From: Henry Ward <45144290+kudosscience@users.noreply.github.com>
Date: Thu, 21 Nov 2024 10:14:59 +0000
Subject: [PATCH 22/22] Fix broken 3rd edition Packt link in README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 96845564..e5657bcd 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ Book link - second edition:
  - [Brazilian Portuguese version](https://novatec.com.br/livros/estruturas-de-dados-algoritmos-em-javascript/)
 
  Book link - third edition:
- - [Packt](https://www.packtpub.com/web-development/learning-javascript-data-structures-and-algorithms-third-edition)
+ - [Packt](https://www.packtpub.com/en-us/product/learning-javascript-data-structures-and-algorithms-9781788624947)
  - [Amazon](http://a.co/cbMlYmJ)
  - [Chinese version](http://www.ituring.com.cn/book/2653)
  - [Brazilian Portuguese version](https://novatec.com.br/livros/estruturas-de-dados-algoritmos-em-javascript-2ed/)