From 0144e775ba498a4cc604d941b52ccd866f074a91 Mon Sep 17 00:00:00 2001 From: hasanalkaf3 Date: Sun, 7 Apr 2024 09:56:39 +0300 Subject: [PATCH 1/2] chore: convert functions to an ES2015 classes --- Conversions/RailwayTimeConversion.js | 4 +- Data-Structures/Array/Reverse.js | 8 +- Data-Structures/Stack/Stack.js | 68 +++--- Data-Structures/Tree/AVLTree.js | 99 ++++---- Data-Structures/Tree/BinarySearchTree.js | 184 +++++++-------- Data-Structures/Tree/Trie.js | 215 +++++++++--------- .../NumberOfSubsetEqualToGivenSum.js | 2 +- Project-Euler/Problem004.js | 2 +- 8 files changed, 297 insertions(+), 285 deletions(-) diff --git a/Conversions/RailwayTimeConversion.js b/Conversions/RailwayTimeConversion.js index 15f837b0da..b499023223 100644 --- a/Conversions/RailwayTimeConversion.js +++ b/Conversions/RailwayTimeConversion.js @@ -24,8 +24,8 @@ const RailwayTimeConversion = (timeString) => { const [hour, minute, secondWithShift] = timeString.split(':') // split second and shift value. const [second, shift] = [ - secondWithShift.substr(0, 2), - secondWithShift.substr(2) + secondWithShift.substring(0, 2), + secondWithShift.substring(2) ] // convert shifted time to not-shift time(Railway time) by using the above explanation. if (shift === 'PM') { diff --git a/Data-Structures/Array/Reverse.js b/Data-Structures/Array/Reverse.js index 79a789c017..a889c67e4b 100644 --- a/Data-Structures/Array/Reverse.js +++ b/Data-Structures/Array/Reverse.js @@ -7,11 +7,9 @@ const Reverse = (arr) => { // limit specifies the amount of Reverse actions - for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) { - const temp = arr[i] - arr[i] = arr[j] - arr[j] = temp - } + for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) + [arr[i], arr[j]] = [arr[j], arr[i]] // Swapping elements ES6 way + return arr } export { Reverse } diff --git a/Data-Structures/Stack/Stack.js b/Data-Structures/Stack/Stack.js index d3001e8020..129f3898c0 100644 --- a/Data-Structures/Stack/Stack.js +++ b/Data-Structures/Stack/Stack.js @@ -9,45 +9,47 @@ // Creates a stack constructor const Stack = (function () { - function Stack() { - // The top of the Stack - this.top = 0 - // The array representation of the stack - this.stack = [] - } - - // Adds a value onto the end of the stack - Stack.prototype.push = function (value) { - this.stack[this.top] = value - this.top++ - } + class Stack { + constructor() { + // The top of the Stack + this.top = 0 + // The array representation of the stack + this.stack = [] + } - // Removes and returns the value at the end of the stack - Stack.prototype.pop = function () { - if (this.top === 0) { - return 'Stack is Empty' + // Adds a value onto the end of the stack + push(value) { + this.stack[this.top] = value + this.top++ } - this.top-- - const result = this.stack[this.top] - this.stack = this.stack.splice(0, this.top) - return result - } + // Removes and returns the value at the end of the stack + pop() { + if (this.top === 0) { + return 'Stack is Empty' + } - // Returns the size of the stack - Stack.prototype.size = function () { - return this.top - } + this.top-- + const result = this.stack[this.top] + this.stack = this.stack.splice(0, this.top) + return result + } - // Returns the value at the end of the stack - Stack.prototype.peek = function () { - return this.stack[this.top - 1] - } + // Returns the size of the stack + size() { + return this.top + } + + // Returns the value at the end of the stack + peek() { + return this.stack[this.top - 1] + } - // To see all the elements in the stack - Stack.prototype.view = function (output = (value) => console.log(value)) { - for (let i = 0; i < this.top; i++) { - output(this.stack[i]) + // To see all the elements in the stack + view(output = (value) => console.log(value)) { + for (let i = 0; i < this.top; i++) { + output(this.stack[i]) + } } } diff --git a/Data-Structures/Tree/AVLTree.js b/Data-Structures/Tree/AVLTree.js index e5abbf3e55..5418c576e4 100644 --- a/Data-Structures/Tree/AVLTree.js +++ b/Data-Structures/Tree/AVLTree.js @@ -32,23 +32,62 @@ let utils * If no argument is sent it uses utils.comparator */ const AVLTree = (function () { - function _avl(comp) { - /** @public comparator function */ - this._comp = undefined - this._comp = comp !== undefined ? comp : utils.comparator() + class _avl { + constructor(comp) { + /** @public comparator function */ + this._comp = undefined + this._comp = comp !== undefined ? comp : utils.comparator() - /** @public root of the AVL Tree */ - this.root = null - /** @public number of elements in AVL Tree */ - this.size = 0 + /** @public root of the AVL Tree */ + this.root = null + /** @public number of elements in AVL Tree */ + this.size = 0 + } + + /* Public Functions */ + /** + * For Adding Elements to AVL Tree + * @param {any} _val + * Since in AVL Tree an element can only occur once so + * if a element exists it return false + * @returns {Boolean} element added or not + */ + add(_val) { + const prevSize = this.size + this.root = insert(this.root, _val, this) + return this.size !== prevSize + } + /** + * TO check is a particular element exists or not + * @param {any} _val + * @returns {Boolean} exists or not + */ + find(_val) { + const temp = searchAVLTree(this.root, _val, this) + return temp != null + } + /** + * + * @param {any} _val + * It is possible that element doesn't exists in tree + * in that case it return false + * @returns {Boolean} if element was found and deleted + */ + remove(_val) { + const prevSize = this.size + this.root = deleteElement(this.root, _val, this) + return prevSize !== this.size + } } // creates new Node Object - const Node = function (val) { - this._val = val - this._left = null - this._right = null - this._height = 1 + class Node { + constructor(val) { + this._val = val + this._left = null + this._right = null + this._height = 1 + } } // get height of a node @@ -199,40 +238,6 @@ const AVLTree = (function () { return searchAVLTree(root._left, val, tree) } - /* Public Functions */ - /** - * For Adding Elements to AVL Tree - * @param {any} _val - * Since in AVL Tree an element can only occur once so - * if a element exists it return false - * @returns {Boolean} element added or not - */ - _avl.prototype.add = function (_val) { - const prevSize = this.size - this.root = insert(this.root, _val, this) - return this.size !== prevSize - } - /** - * TO check is a particular element exists or not - * @param {any} _val - * @returns {Boolean} exists or not - */ - _avl.prototype.find = function (_val) { - const temp = searchAVLTree(this.root, _val, this) - return temp != null - } - /** - * - * @param {any} _val - * It is possible that element doesn't exists in tree - * in that case it return false - * @returns {Boolean} if element was found and deleted - */ - _avl.prototype.remove = function (_val) { - const prevSize = this.size - this.root = deleteElement(this.root, _val, this) - return prevSize !== this.size - } return _avl })() diff --git a/Data-Structures/Tree/BinarySearchTree.js b/Data-Structures/Tree/BinarySearchTree.js index c86a2995c0..abbcc3fb62 100644 --- a/Data-Structures/Tree/BinarySearchTree.js +++ b/Data-Structures/Tree/BinarySearchTree.js @@ -13,77 +13,79 @@ // class Node const Node = (function Node() { // Node in the tree - function Node(val) { - this.value = val - this.left = null - this.right = null - } - - // Search the tree for a value - Node.prototype.search = function (val) { - if (this.value === val) { - return this - } else if (val < this.value && this.left !== null) { - return this.left.search(val) - } else if (val > this.value && this.right !== null) { - return this.right.search(val) + class Node { + constructor(val) { + this.value = val + this.left = null + this.right = null } - return null - } - // Visit a node - Node.prototype.visit = function (output = (value) => console.log(value)) { - // Recursively go left - if (this.left !== null) { - this.left.visit() - } - // Print out value - output(this.value) - // Recursively go right - if (this.right !== null) { - this.right.visit() + // Search the tree for a value + search(val) { + if (this.value === val) { + return this + } else if (val < this.value && this.left !== null) { + return this.left.search(val) + } else if (val > this.value && this.right !== null) { + return this.right.search(val) + } + return null } - } - // Add a node - Node.prototype.addNode = function (n) { - if (n.value < this.value) { - if (this.left === null) { - this.left = n - } else { - this.left.addNode(n) + // Visit a node + visit(output = (value) => console.log(value)) { + // Recursively go left + if (this.left !== null) { + this.left.visit() } - } else if (n.value > this.value) { - if (this.right === null) { - this.right = n - } else { - this.right.addNode(n) + // Print out value + output(this.value) + // Recursively go right + if (this.right !== null) { + this.right.visit() } } - } - // remove a node - Node.prototype.removeNode = function (val) { - if (val === this.value) { - if (!this.left && !this.right) { - return null - } else { - if (this.left) { - const leftMax = maxVal(this.left) - this.value = leftMax - this.left = this.left.removeNode(leftMax) + // Add a node + addNode(n) { + if (n.value < this.value) { + if (this.left === null) { + this.left = n } else { - const rightMin = minVal(this.right) - this.value = rightMin - this.right = this.right.removeNode(rightMin) + this.left.addNode(n) + } + } else if (n.value > this.value) { + if (this.right === null) { + this.right = n + } else { + this.right.addNode(n) } } - } else if (val < this.value) { - this.left = this.left && this.left.removeNode(val) - } else if (val > this.value) { - this.right = this.right && this.right.removeNode(val) } - return this + + // remove a node + removeNode(val) { + if (val === this.value) { + if (!this.left && !this.right) { + return null + } else { + if (this.left) { + const leftMax = maxVal(this.left) + this.value = leftMax + this.left = this.left.removeNode(leftMax) + } else { + const rightMin = minVal(this.right) + this.value = rightMin + this.right = this.right.removeNode(rightMin) + } + } + } else if (val < this.value) { + this.left = this.left && this.left.removeNode(val) + } else if (val > this.value) { + this.right = this.right && this.right.removeNode(val) + } + return this + } } // find maximum value in the tree @@ -107,44 +109,46 @@ const Node = (function Node() { // class Tree const Tree = (function () { - function Tree() { - // Just store the root - this.root = null - } + class Tree { + constructor() { + // Just store the root + this.root = null + } - // Inorder traversal - Tree.prototype.traverse = function () { - if (!this.root) { - // No nodes are there in the tree till now - return + // Inorder traversal + traverse() { + if (!this.root) { + // No nodes are there in the tree till now + return + } + this.root.visit() } - this.root.visit() - } - // Start by searching the root - Tree.prototype.search = function (val) { - const found = this.root.search(val) - if (found !== null) { - return found.value + // Start by searching the root + search(val) { + const found = this.root.search(val) + if (found !== null) { + return found.value + } + // not found + return null } - // not found - return null - } - // Add a new value to the tree - Tree.prototype.addValue = function (val) { - const n = new Node(val) - if (this.root === null) { - this.root = n - } else { - this.root.addNode(n) + // Add a new value to the tree + addValue(val) { + const n = new Node(val) + if (this.root === null) { + this.root = n + } else { + this.root.addNode(n) + } } - } - // remove a value from the tree - Tree.prototype.removeValue = function (val) { - // remove something if root exists - this.root = this.root && this.root.removeNode(val) + // remove a value from the tree + removeValue(val) { + // remove something if root exists + this.root = this.root && this.root.removeNode(val) + } } // returns the constructor diff --git a/Data-Structures/Tree/Trie.js b/Data-Structures/Tree/Trie.js index ea59e53846..0d4018f74f 100644 --- a/Data-Structures/Tree/Trie.js +++ b/Data-Structures/Tree/Trie.js @@ -1,129 +1,132 @@ -const TrieNode = function TrieNode(key, parent) { - this.key = key - this.count = 0 - this.children = Object.create(null) - if (parent === undefined) { - this.parent = null - } else { - this.parent = parent +class TrieNode { + constructor(key, parent) { + this.key = key + this.count = 0 + this.children = Object.create(null) + if (parent === undefined) { + this.parent = null + } else { + this.parent = parent + } } } -function Trie() { - // create only root with null key and parent - this.root = new TrieNode(null, null) -} +class Trie { + constructor() { + // create only root with null key and parent + this.root = new TrieNode(null, null) + } -// Recursively finds the occurrence of all words in a given node -Trie.findAllWords = function (root, word, output) { - if (root === null) return - if (root.count > 0) { - if (typeof output === 'object') { - output.push({ word, count: root.count }) + // Recursively finds the occurrence of all words in a given node + static findAllWords(root, word, output) { + if (root === null) return + if (root.count > 0) { + if (typeof output === 'object') { + output.push({ word, count: root.count }) + } + } + let key + for (key in root.children) { + word += key + this.findAllWords(root.children[key], word, output) + word = word.slice(0, -1) } } - let key - for (key in root.children) { - word += key - this.findAllWords(root.children[key], word, output) - word = word.slice(0, -1) - } -} -Trie.prototype.insert = function (word) { - if (typeof word !== 'string') return - if (word === '') { - this.root.count += 1 - return - } - let node = this.root - const len = word.length - let i - for (i = 0; i < len; i++) { - if (node.children[word.charAt(i)] === undefined) { - node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) + insert(word) { + if (typeof word !== 'string') return + if (word === '') { + this.root.count += 1 + return + } + let node = this.root + const len = word.length + let i + for (i = 0; i < len; i++) { + if (node.children[word.charAt(i)] === undefined) { + node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) + } + node = node.children[word.charAt(i)] } - node = node.children[word.charAt(i)] + node.count += 1 } - node.count += 1 -} -Trie.prototype.findPrefix = function (word) { - if (typeof word !== 'string') return null - let node = this.root - const len = word.length - let i - // After end of this loop node will be at desired prefix - for (i = 0; i < len; i++) { - if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists - node = node.children[word.charAt(i)] + findPrefix(word) { + if (typeof word !== 'string') return null + let node = this.root + const len = word.length + let i + // After end of this loop node will be at desired prefix + for (i = 0; i < len; i++) { + if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists + node = node.children[word.charAt(i)] + } + return node } - return node -} -Trie.prototype.remove = function (word, count) { - if (typeof word !== 'string') return - if (typeof count !== 'number') count = 1 - else if (count <= 0) return + remove(word, count) { + if (typeof word !== 'string') return + if (typeof count !== 'number') count = 1 + else if (count <= 0) return - // for empty string just delete count of root - if (word === '') { - if (this.root.count >= count) this.root.count -= count - else this.root.count = 0 - return - } + // for empty string just delete count of root + if (word === '') { + if (this.root.count >= count) this.root.count -= count + else this.root.count = 0 + return + } - let child = this.root - const len = word.length - let i, key - // child: node which is to be deleted - for (i = 0; i < len; i++) { - key = word.charAt(i) - if (child.children[key] === undefined) return - child = child.children[key] - } + let child = this.root + const len = word.length + let i, key + // child: node which is to be deleted + for (i = 0; i < len; i++) { + key = word.charAt(i) + if (child.children[key] === undefined) return + child = child.children[key] + } - // Delete no of occurrences specified - if (child.count >= count) child.count -= count - else child.count = 0 + // Delete no of occurrences specified + if (child.count >= count) child.count -= count + else child.count = 0 - // If some occurrences are left we don't delete it or else - // if the object forms some other objects prefix we don't delete it - // For checking an empty object - // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object - if ( - child.count <= 0 && - Object.keys(child.children).length && - child.children.constructor === Object - ) { - child.parent.children[child.key] = undefined + // If some occurrences are left we don't delete it or else + // if the object forms some other objects prefix we don't delete it + // For checking an empty object + // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object + if ( + child.count <= 0 && + Object.keys(child.children).length && + child.children.constructor === Object + ) { + child.parent.children[child.key] = undefined + } } -} -Trie.prototype.findAllWords = function (prefix) { - const output = [] - // find the node with provided prefix - const node = this.findPrefix(prefix) - // No such prefix exists - if (node === null) return output - Trie.findAllWords(node, prefix, output) - return output -} - -Trie.prototype.contains = function (word) { - // find the node with given prefix - const node = this.findPrefix(word) - // No such word exists + findAllWords(prefix) { + const output = [] + // find the node with provided prefix + const node = this.findPrefix(prefix) + // No such prefix exists + if (node === null) return output + Trie.findAllWords(node, prefix, output) + return output + } - return node !== null && node.count !== 0 -} + contains(word) { + // find the node with given prefix + const node = this.findPrefix(word) + // No such word exists + return node !== null && node.count !== 0 + } -Trie.prototype.findOccurrences = function (word) { - // find the node with given prefix - const node = this.findPrefix(word) - // No such word exists - if (node === null) return 0 - return node.count + findOccurrences(word) { + // find the node with given prefix + const node = this.findPrefix(word) + // No such word exists + if (node === null) return 0 + return node.count + } } export { Trie } diff --git a/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js b/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js index dee12f8de9..48905c39e2 100644 --- a/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js +++ b/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js @@ -4,7 +4,7 @@ determine the total number of the subset with sum equal to the given sum. */ /* - Given solution is O(n*sum) Time complexity and O(sum) Space complexity + Given solution is O(n*sum) Time complexity and O(sum) Space complexity */ function NumberOfSubsetSum(array, sum) { const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i diff --git a/Project-Euler/Problem004.js b/Project-Euler/Problem004.js index 34fa87471d..7c85dfdb85 100644 --- a/Project-Euler/Problem004.js +++ b/Project-Euler/Problem004.js @@ -1,6 +1,6 @@ // https://projecteuler.net/problem=4 /* A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. - Find the largest palindrome made from the product of two 3-digit numbers. + Find the largest palindrome made from the product of two 3-digit numbers. */ export const largestPalindromic = (digits) => { let i From 554a002f3bb5145ee0fa50b4942ad032c4212d01 Mon Sep 17 00:00:00 2001 From: hasanalkaf3 Date: Tue, 9 Apr 2024 00:59:21 +0300 Subject: [PATCH 2/2] remove unnecessary functions --- Data-Structures/Array/Reverse.js | 2 +- Data-Structures/Stack/Stack.js | 74 +++---- Data-Structures/Tree/AVLTree.js | 358 +++++++++++++++---------------- 3 files changed, 214 insertions(+), 220 deletions(-) diff --git a/Data-Structures/Array/Reverse.js b/Data-Structures/Array/Reverse.js index a889c67e4b..ca08f35f8a 100644 --- a/Data-Structures/Array/Reverse.js +++ b/Data-Structures/Array/Reverse.js @@ -8,7 +8,7 @@ const Reverse = (arr) => { // limit specifies the amount of Reverse actions for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) - [arr[i], arr[j]] = [arr[j], arr[i]] // Swapping elements ES6 way + [arr[i], arr[j]] = [arr[j], arr[i]] return arr } diff --git a/Data-Structures/Stack/Stack.js b/Data-Structures/Stack/Stack.js index 129f3898c0..d8531fdebf 100644 --- a/Data-Structures/Stack/Stack.js +++ b/Data-Structures/Stack/Stack.js @@ -8,52 +8,48 @@ // Functions: push, pop, peek, view, length // Creates a stack constructor -const Stack = (function () { - class Stack { - constructor() { - // The top of the Stack - this.top = 0 - // The array representation of the stack - this.stack = [] - } - - // Adds a value onto the end of the stack - push(value) { - this.stack[this.top] = value - this.top++ - } +class Stack { + constructor() { + // The top of the Stack + this.top = 0 + // The array representation of the stack + this.stack = [] + } - // Removes and returns the value at the end of the stack - pop() { - if (this.top === 0) { - return 'Stack is Empty' - } + // Adds a value onto the end of the stack + push(value) { + this.stack[this.top] = value + this.top++ + } - this.top-- - const result = this.stack[this.top] - this.stack = this.stack.splice(0, this.top) - return result + // Removes and returns the value at the end of the stack + pop() { + if (this.top === 0) { + return 'Stack is Empty' } - // Returns the size of the stack - size() { - return this.top - } + this.top-- + const result = this.stack[this.top] + this.stack = this.stack.splice(0, this.top) + return result + } - // Returns the value at the end of the stack - peek() { - return this.stack[this.top - 1] - } + // Returns the size of the stack + size() { + return this.top + } - // To see all the elements in the stack - view(output = (value) => console.log(value)) { - for (let i = 0; i < this.top; i++) { - output(this.stack[i]) - } - } + // Returns the value at the end of the stack + peek() { + return this.stack[this.top - 1] } - return Stack -})() + // To see all the elements in the stack + view(output = (value) => console.log(value)) { + for (let i = 0; i < this.top; i++) { + output(this.stack[i]) + } + } +} export { Stack } diff --git a/Data-Structures/Tree/AVLTree.js b/Data-Structures/Tree/AVLTree.js index 5418c576e4..dd673a9330 100644 --- a/Data-Structures/Tree/AVLTree.js +++ b/Data-Structures/Tree/AVLTree.js @@ -31,215 +31,213 @@ let utils * @argument comp - A function used by AVL Tree For Comparison * If no argument is sent it uses utils.comparator */ -const AVLTree = (function () { - class _avl { - constructor(comp) { - /** @public comparator function */ - this._comp = undefined - this._comp = comp !== undefined ? comp : utils.comparator() +class AVLTree { + constructor(comp) { + /** @public comparator function */ + this._comp = undefined + this._comp = comp !== undefined ? comp : utils.comparator() - /** @public root of the AVL Tree */ - this.root = null - /** @public number of elements in AVL Tree */ - this.size = 0 - } + /** @public root of the AVL Tree */ + this.root = null + /** @public number of elements in AVL Tree */ + this.size = 0 + } - /* Public Functions */ - /** - * For Adding Elements to AVL Tree - * @param {any} _val - * Since in AVL Tree an element can only occur once so - * if a element exists it return false - * @returns {Boolean} element added or not - */ - add(_val) { - const prevSize = this.size - this.root = insert(this.root, _val, this) - return this.size !== prevSize - } - /** - * TO check is a particular element exists or not - * @param {any} _val - * @returns {Boolean} exists or not - */ - find(_val) { - const temp = searchAVLTree(this.root, _val, this) - return temp != null - } - /** - * - * @param {any} _val - * It is possible that element doesn't exists in tree - * in that case it return false - * @returns {Boolean} if element was found and deleted - */ - remove(_val) { - const prevSize = this.size - this.root = deleteElement(this.root, _val, this) - return prevSize !== this.size - } + /* Public Functions */ + /** + * For Adding Elements to AVL Tree + * @param {any} _val + * Since in AVL Tree an element can only occur once so + * if a element exists it return false + * @returns {Boolean} element added or not + */ + add(_val) { + const prevSize = this.size + this.root = insert(this.root, _val, this) + return this.size !== prevSize } - // creates new Node Object - class Node { - constructor(val) { - this._val = val - this._left = null - this._right = null - this._height = 1 - } + /** + * TO check is a particular element exists or not + * @param {any} _val + * @returns {Boolean} exists or not + */ + find(_val) { + const temp = searchAVLTree(this.root, _val, this) + return temp != null } - // get height of a node - const getHeight = function (node) { - if (node == null) { - return 0 - } - return node._height + /** + * + * @param {any} _val + * It is possible that element doesn't exists in tree + * in that case it return false + * @returns {Boolean} if element was found and deleted + */ + remove(_val) { + const prevSize = this.size + this.root = deleteElement(this.root, _val, this) + return prevSize !== this.size } +} - // height difference or balance factor of a node - const getHeightDifference = function (node) { - return node == null ? 0 : getHeight(node._left) - getHeight(node._right) +// creates new Node Object +class Node { + constructor(val) { + this._val = val + this._left = null + this._right = null + this._height = 1 } +} - // update height of a node based on children's heights - const updateHeight = function (node) { - if (node == null) { - return - } - node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1 +// get height of a node +const getHeight = function (node) { + if (node == null) { + return 0 + } + return node._height +} + +// height difference or balance factor of a node +const getHeightDifference = function (node) { + return node == null ? 0 : getHeight(node._left) - getHeight(node._right) +} + +// update height of a node based on children's heights +const updateHeight = function (node) { + if (node == null) { + return } + node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1 +} + +// Helper: To check if the balanceFactor is valid +const isValidBalanceFactor = (balanceFactor) => + [0, 1, -1].includes(balanceFactor) - // Helper: To check if the balanceFactor is valid - const isValidBalanceFactor = (balanceFactor) => - [0, 1, -1].includes(balanceFactor) +// rotations of AVL Tree +const leftRotate = function (node) { + const temp = node._right + node._right = temp._left + temp._left = node + updateHeight(node) + updateHeight(temp) + return temp +} +const rightRotate = function (node) { + const temp = node._left + node._left = temp._right + temp._right = node + updateHeight(node) + updateHeight(temp) + return temp +} - // rotations of AVL Tree - const leftRotate = function (node) { - const temp = node._right - node._right = temp._left - temp._left = node - updateHeight(node) - updateHeight(temp) - return temp +// check if tree is balanced else balance it for insertion +const insertBalance = function (node, _val, balanceFactor, tree) { + if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) { + return rightRotate(node) // Left Left Case } - const rightRotate = function (node) { - const temp = node._left - node._left = temp._right - temp._right = node - updateHeight(node) - updateHeight(temp) - return temp + if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) { + return leftRotate(node) // Right Right Case } + if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) { + node._left = leftRotate(node._left) // Left Right Case + return rightRotate(node) + } + node._right = rightRotate(node._right) + return leftRotate(node) +} - // check if tree is balanced else balance it for insertion - const insertBalance = function (node, _val, balanceFactor, tree) { - if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) { - return rightRotate(node) // Left Left Case - } - if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) { - return leftRotate(node) // Right Right Case - } - if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) { - node._left = leftRotate(node._left) // Left Right Case - return rightRotate(node) +// check if tree is balanced after deletion +const delBalance = function (node) { + const balanceFactor1 = getHeightDifference(node) + if (isValidBalanceFactor(balanceFactor1)) { + return node + } + if (balanceFactor1 > 1) { + if (getHeightDifference(node._left) >= 0) { + return rightRotate(node) // Left Left } + node._left = leftRotate(node._left) + return rightRotate(node) // Left Right + } + if (getHeightDifference(node._right) > 0) { node._right = rightRotate(node._right) - return leftRotate(node) + return leftRotate(node) // Right Left } + return leftRotate(node) // Right Right +} - // check if tree is balanced after deletion - const delBalance = function (node) { - const balanceFactor1 = getHeightDifference(node) - if (isValidBalanceFactor(balanceFactor1)) { - return node - } - if (balanceFactor1 > 1) { - if (getHeightDifference(node._left) >= 0) { - return rightRotate(node) // Left Left - } - node._left = leftRotate(node._left) - return rightRotate(node) // Left Right - } - if (getHeightDifference(node._right) > 0) { - node._right = rightRotate(node._right) - return leftRotate(node) // Right Left - } - return leftRotate(node) // Right Right +// implement avl tree insertion +const insert = function (root, val, tree) { + if (root == null) { + tree.size++ + return new Node(val) } - - // implement avl tree insertion - const insert = function (root, val, tree) { - if (root == null) { - tree.size++ - return new Node(val) - } - if (tree._comp(root._val, val) < 0) { - root._right = insert(root._right, val, tree) - } else if (tree._comp(root._val, val) > 0) { - root._left = insert(root._left, val, tree) - } else { - return root - } - updateHeight(root) - const balanceFactor = getHeightDifference(root) - return isValidBalanceFactor(balanceFactor) - ? root - : insertBalance(root, val, balanceFactor, tree) + if (tree._comp(root._val, val) < 0) { + root._right = insert(root._right, val, tree) + } else if (tree._comp(root._val, val) > 0) { + root._left = insert(root._left, val, tree) + } else { + return root } + updateHeight(root) + const balanceFactor = getHeightDifference(root) + return isValidBalanceFactor(balanceFactor) + ? root + : insertBalance(root, val, balanceFactor, tree) +} - // delete am element - const deleteElement = function (root, _val, tree) { - if (root == null) { - return root - } - if (tree._comp(root._val, _val) === 0) { - // key found case - if (root._left === null && root._right === null) { - root = null - tree.size-- - } else if (root._left === null) { - root = root._right - tree.size-- - } else if (root._right === null) { - root = root._left - tree.size-- - } else { - let temp = root._right - while (temp._left != null) { - temp = temp._left - } - root._val = temp._val - root._right = deleteElement(root._right, temp._val, tree) - } +// delete am element +const deleteElement = function (root, _val, tree) { + if (root == null) { + return root + } + if (tree._comp(root._val, _val) === 0) { + // key found case + if (root._left === null && root._right === null) { + root = null + tree.size-- + } else if (root._left === null) { + root = root._right + tree.size-- + } else if (root._right === null) { + root = root._left + tree.size-- } else { - if (tree._comp(root._val, _val) < 0) { - root._right = deleteElement(root._right, _val, tree) - } else { - root._left = deleteElement(root._left, _val, tree) + let temp = root._right + while (temp._left != null) { + temp = temp._left } + root._val = temp._val + root._right = deleteElement(root._right, temp._val, tree) + } + } else { + if (tree._comp(root._val, _val) < 0) { + root._right = deleteElement(root._right, _val, tree) + } else { + root._left = deleteElement(root._left, _val, tree) } - updateHeight(root) - root = delBalance(root) + } + updateHeight(root) + root = delBalance(root) + return root +} +// search tree for a element +const searchAVLTree = function (root, val, tree) { + if (root == null) { + return null + } + if (tree._comp(root._val, val) === 0) { return root } - // search tree for a element - const searchAVLTree = function (root, val, tree) { - if (root == null) { - return null - } - if (tree._comp(root._val, val) === 0) { - return root - } - if (tree._comp(root._val, val) < 0) { - return searchAVLTree(root._right, val, tree) - } - return searchAVLTree(root._left, val, tree) + if (tree._comp(root._val, val) < 0) { + return searchAVLTree(root._right, val, tree) } - - return _avl -})() + return searchAVLTree(root._left, val, tree) +} /** * A Code for Testing the AVLTree