From 0b922f73f28ab88556609157440ff903dbdd8f1f Mon Sep 17 00:00:00 2001 From: Rahul Raj Date: Tue, 15 Feb 2022 20:24:01 +0530 Subject: [PATCH 1/5] Improving the coding standard for AvLTree Data Structure --- Data-Structures/Tree/AVLTree.js | 516 ++++++++++++++++---------------- 1 file changed, 250 insertions(+), 266 deletions(-) diff --git a/Data-Structures/Tree/AVLTree.js b/Data-Structures/Tree/AVLTree.js index 45f1e682d4..816c14e5b4 100644 --- a/Data-Structures/Tree/AVLTree.js +++ b/Data-Structures/Tree/AVLTree.js @@ -3,270 +3,254 @@ * [Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) * [A video lecture](http://www.youtube.com/watch?v=TbvhGcf6UJU) */ -'use strict' + 'use strict' -/** - * A utility class for comparator - * A comparator is expected to have following structure - * - * comp(a, b) RETURN < 0 if a < b - * RETURN > 0 if a > b - * MUST RETURN 0 if a == b - */ -let utils; -(function (_utils) { - function comparator () { - return function (v1, v2) { - if (v1 < v2) { - return -1 - } else if (v2 < v1) { - return 1 - } else { - return 0 - } - } - } - _utils.comparator = comparator -})(utils || (utils = {})) - -/** - * @constructor - * A class for AVL Tree - * @argument comp - A function used by AVL Tree For Comparison - * If no argument is sent it uses utils.comparator - */ -const AVLTree = (function () { - function _avl (comp) { - /** @public comparator function */ - this._comp = undefined - if (comp !== undefined) { - this._comp = comp - } else { - this._comp = utils.comparator() - } - /** @public root of the AVL Tree */ - this.root = null - /** @public number of elements in AVL Tree */ - this.size = 0 - } - // creates new Node Object - const Node = function (val) { - this._val = val - this._left = null - this._right = null - this._height = 1 - } - // get height of a node - const getH = function (node) { - if (node == null) { return 0 } - return node._height - } - // height difference or balance factor of a node - const getHDiff = function (node) { - if (node == null) { return 0 } else { return getH(node._left) - getH(node._right) } - } - // update height of a node based on children's heights - const updateH = function (node) { - if (node == null) { - return - } - node._height = Math.max(getH(node._left), getH(node._right)) + 1 - } - // rotations of AVL Tree - const leftRotate = function (node) { - const temp = node._right - node._right = temp._left - temp._left = node - updateH(node) - updateH(temp) - return temp - } - const rightRotate = function (node) { - const temp = node._left - node._left = temp._right - temp._right = node - updateH(node) - updateH(temp) - return temp - } - // check if tree is balanced else balance it for insertion - const insertBalance = function (node, _val, balanceFactor) { - if (balanceFactor > 1 && _val < node._left._val) { - return rightRotate(node) // Left Left Case - } else if (balanceFactor < 1 && _val > node._right._val) { - return leftRotate(node) // Right Right Case - } else if (balanceFactor > 1 && _val > node._left._val) { - node._left = leftRotate(node._left) // Left Right Case - return rightRotate(node) - } - node._right = rightRotate(node._right) - return leftRotate(node) - } - // check if tree is balanced after deletion - const delBalance = function (node) { - const balanceFactor1 = getHDiff(node) - if (balanceFactor1 === 0 || balanceFactor1 === 1 || balanceFactor1 === -1) { - return node - } - if (balanceFactor1 > 1) { - if (getHDiff(node._left) >= 0) { - return rightRotate(node) // Left Left - } - node._left = leftRotate(node._left) - return rightRotate(node) // Left Right - } - if (getHDiff(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) - } else 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 - } - updateH(root) - const balanceFactor = getHDiff(root) - if (balanceFactor === 0 || balanceFactor === 1 || balanceFactor === -1) { - return root - } - return insertBalance(root, val, balanceFactor) - } - // delete a element - const del = function (root, _val, tree) { - if (root == null) { - return root - } else 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 = del(root._right, temp._val, tree) - } - } else { - if (tree._comp(root._val, _val) < 0) { - root._right = del(root._right, _val, tree) - } else { - root._left = del(root._left, _val, tree) - } - } - updateH(root) - root = delBalance(root) - return root - } - // search tree for a element - const search = function (root, val, tree) { - if (root == null) { - return null - } else if (tree._comp(root._val, val) === 0) { - return root - } else if (tree._comp(root._val, val) < 0) { - return search(root._right, val, tree) - } - return search(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) - if (this.size === prevSize) { - return false - } - return true - } - /** - * TO check is a particular element exists or not - * @param {any} _val - * @returns {Boolean} exists or not - */ - _avl.prototype.find = function (_val) { - const temp = search(this.root, _val, this) - if (temp != null) { - return true - } - return false - } - /** - * - * @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 = del(this.root, _val, this) - if (prevSize === this.size) { - return false - } - return true - } - return _avl -}()) - -/** - * A Code for Testing the AVLTree - */ -// (function test () { -// const newAVL = new AVLTree() -// const size = Math.floor(Math.random() * 1000000) -// let uniques = 0 -// let i, temp, j -// const array = [] -// for (i = 0; i < size; i++) { -// temp = Math.floor(Math.random() * Number.MAX_VALUE) -// if (newAVL.add(temp)) { -// uniques++ -// array.push(temp) -// } -// } -// if (newAVL.size !== uniques) { -// throw new Error('elements not inserted properly') -// } -// const findTestSize = Math.floor(Math.random() * uniques) -// for (i = 0; i < findTestSize; i++) { -// j = Math.floor(Math.random() * uniques) -// if (!newAVL.find(array[j])) { -// throw new Error('inserted elements not found') -// } -// } -// const deleteTestSize = Math.floor(uniques * Math.random()) -// for (i = 0; i < deleteTestSize; i++) { -// j = Math.floor(Math.random() * uniques) -// temp = array[j] -// if (newAVL.find(temp)) { -// if (!newAVL.remove(temp)) { -// throw new Error('delete not working properly') -// } -// } -// } -// })() - -export { AVLTree } + /** + * A utility class for comparator + * A comparator is expected to have following structure + * + * comp(a, b) RETURN < 0 if a < b + * RETURN > 0 if a > b + * MUST RETURN 0 if a == b + */ + let utils; + (function (_utils) { + function comparator () { + return function (v1, v2) { + if (v1 < v2) return -1 + if (v2 < v1) return 1 + return 0 + } + } + _utils.comparator = comparator + })(utils || (utils = {})) + + const isValidBalanceFactor = (balanceFactor) => [0,1,-1].includes(balanceFactor) + + /** + * @constructor + * A class for AVL Tree + * @argument comp - A function used by AVL Tree For Comparison + * 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() + + /** @public root of the AVL Tree */ + this.root = null + /** @public number of elements in AVL Tree */ + this.size = 0 + } + // creates new Node Object + const Node = function (val) { + this._val = val + this._left = null + this._right = null + this._height = 1 + } + // get height of a node + const getH = function (node) { + if (node == null) { return 0 } + return node._height + } + // height difference or balance factor of a node + const getHDiff = function (node) { + return node == null ? 0 : getH(node._left) - getH(node._right) + } + // update height of a node based on children's heights + const updateH = function (node) { + if (node == null) { return } + node._height = Math.max(getH(node._left), getH(node._right)) + 1 + } + // rotations of AVL Tree + const leftRotate = function (node) { + const temp = node._right + node._right = temp._left + temp._left = node + updateH(node) + updateH(temp) + return temp + } + const rightRotate = function (node) { + const temp = node._left + node._left = temp._right + temp._right = node + updateH(node) + updateH(temp) + return temp + } + // check if tree is balanced else balance it for insertion + const insertBalance = function (node, _val, balanceFactor) { + if (balanceFactor > 1 && _val < node._left._val) { + return rightRotate(node) // Left Left Case + } + if (balanceFactor < 1 && _val > node._right._val) { + return leftRotate(node) // Right Right Case + } + if (balanceFactor > 1 && _val > node._left._val) { + node._left = leftRotate(node._left) // Left Right Case + return rightRotate(node) + } + node._right = rightRotate(node._right) + return leftRotate(node) + } + // check if tree is balanced after deletion + const delBalance = function (node) { + const balanceFactor1 = getHDiff(node) + if (isValidBalanceFactor(balanceFactor1)) { + return node + } + if (balanceFactor1 > 1) { + if (getHDiff(node._left) >= 0) { + return rightRotate(node) // Left Left + } + node._left = leftRotate(node._left) + return rightRotate(node) // Left Right + } + if (getHDiff(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) + } + 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 + } + updateH(root) + const balanceFactor = getHDiff(root) + return isValidBalanceFactor(balanceFactor) ? root : insertBalance(root, val, balanceFactor) + } + // delete a element + const del = 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 = del(root._right, temp._val, tree) + } + } else { + if (tree._comp(root._val, _val) < 0) { + root._right = del(root._right, _val, tree) + } else { + root._left = del(root._left, _val, tree) + } + } + updateH(root) + root = delBalance(root) + return root + } + // search tree for a element + const search = 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 search(root._right, val, tree) + } + return search(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 = search(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 = del(this.root, _val, this) + return prevSize !== this.size + } + return _avl + }()) + + /** + * A Code for Testing the AVLTree + */ + // (function test () { + // const newAVL = new AVLTree() + // const size = Math.floor(Math.random() * 1000000) + // let uniques = 0 + // let i, temp, j + // const array = [] + // for (i = 0; i < size; i++) { + // temp = Math.floor(Math.random() * Number.MAX_VALUE) + // if (newAVL.add(temp)) { + // uniques++ + // array.push(temp) + // } + // } + // if (newAVL.size !== uniques) { + // throw new Error('elements not inserted properly') + // } + // const findTestSize = Math.floor(Math.random() * uniques) + // for (i = 0; i < findTestSize; i++) { + // j = Math.floor(Math.random() * uniques) + // if (!newAVL.find(array[j])) { + // throw new Error('inserted elements not found') + // } + // } + // const deleteTestSize = Math.floor(uniques * Math.random()) + // for (i = 0; i < deleteTestSize; i++) { + // j = Math.floor(Math.random() * uniques) + // temp = array[j] + // if (newAVL.find(temp)) { + // if (!newAVL.remove(temp)) { + // throw new Error('delete not working properly') + // } + // } + // } + // })() + + export { AVLTree } + \ No newline at end of file From f19fff890d81cb0fda44ad6ee477a52a51febdb7 Mon Sep 17 00:00:00 2001 From: Rahul Raj Date: Wed, 16 Feb 2022 12:04:20 +0530 Subject: [PATCH 2/5] Test case creation for AVLTree ~ Created test cases for AVL Tree ~ Indentation fix for AVLTree.js --- Data-Structures/Tree/AVLTree.js | 509 +++++++++++----------- Data-Structures/Tree/test/AVLTree.test.js | 32 ++ 2 files changed, 291 insertions(+), 250 deletions(-) create mode 100644 Data-Structures/Tree/test/AVLTree.test.js diff --git a/Data-Structures/Tree/AVLTree.js b/Data-Structures/Tree/AVLTree.js index 816c14e5b4..0cb7f8e8f3 100644 --- a/Data-Structures/Tree/AVLTree.js +++ b/Data-Structures/Tree/AVLTree.js @@ -3,254 +3,263 @@ * [Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) * [A video lecture](http://www.youtube.com/watch?v=TbvhGcf6UJU) */ - 'use strict' +'use strict' - /** - * A utility class for comparator - * A comparator is expected to have following structure - * - * comp(a, b) RETURN < 0 if a < b - * RETURN > 0 if a > b - * MUST RETURN 0 if a == b - */ - let utils; - (function (_utils) { - function comparator () { - return function (v1, v2) { - if (v1 < v2) return -1 - if (v2 < v1) return 1 - return 0 - } - } - _utils.comparator = comparator - })(utils || (utils = {})) - - const isValidBalanceFactor = (balanceFactor) => [0,1,-1].includes(balanceFactor) - - /** - * @constructor - * A class for AVL Tree - * @argument comp - A function used by AVL Tree For Comparison - * 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() - - /** @public root of the AVL Tree */ - this.root = null - /** @public number of elements in AVL Tree */ - this.size = 0 - } - // creates new Node Object - const Node = function (val) { - this._val = val - this._left = null - this._right = null - this._height = 1 - } - // get height of a node - const getH = function (node) { - if (node == null) { return 0 } - return node._height - } - // height difference or balance factor of a node - const getHDiff = function (node) { - return node == null ? 0 : getH(node._left) - getH(node._right) - } - // update height of a node based on children's heights - const updateH = function (node) { - if (node == null) { return } - node._height = Math.max(getH(node._left), getH(node._right)) + 1 - } - // rotations of AVL Tree - const leftRotate = function (node) { - const temp = node._right - node._right = temp._left - temp._left = node - updateH(node) - updateH(temp) - return temp - } - const rightRotate = function (node) { - const temp = node._left - node._left = temp._right - temp._right = node - updateH(node) - updateH(temp) - return temp - } - // check if tree is balanced else balance it for insertion - const insertBalance = function (node, _val, balanceFactor) { - if (balanceFactor > 1 && _val < node._left._val) { - return rightRotate(node) // Left Left Case - } - if (balanceFactor < 1 && _val > node._right._val) { - return leftRotate(node) // Right Right Case - } - if (balanceFactor > 1 && _val > node._left._val) { - node._left = leftRotate(node._left) // Left Right Case - return rightRotate(node) - } - node._right = rightRotate(node._right) - return leftRotate(node) - } - // check if tree is balanced after deletion - const delBalance = function (node) { - const balanceFactor1 = getHDiff(node) - if (isValidBalanceFactor(balanceFactor1)) { - return node - } - if (balanceFactor1 > 1) { - if (getHDiff(node._left) >= 0) { - return rightRotate(node) // Left Left - } - node._left = leftRotate(node._left) - return rightRotate(node) // Left Right - } - if (getHDiff(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) - } - 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 - } - updateH(root) - const balanceFactor = getHDiff(root) - return isValidBalanceFactor(balanceFactor) ? root : insertBalance(root, val, balanceFactor) - } - // delete a element - const del = 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 = del(root._right, temp._val, tree) - } - } else { - if (tree._comp(root._val, _val) < 0) { - root._right = del(root._right, _val, tree) - } else { - root._left = del(root._left, _val, tree) - } - } - updateH(root) - root = delBalance(root) - return root - } - // search tree for a element - const search = 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 search(root._right, val, tree) - } - return search(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 = search(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 = del(this.root, _val, this) - return prevSize !== this.size - } - return _avl - }()) - - /** - * A Code for Testing the AVLTree - */ - // (function test () { - // const newAVL = new AVLTree() - // const size = Math.floor(Math.random() * 1000000) - // let uniques = 0 - // let i, temp, j - // const array = [] - // for (i = 0; i < size; i++) { - // temp = Math.floor(Math.random() * Number.MAX_VALUE) - // if (newAVL.add(temp)) { - // uniques++ - // array.push(temp) - // } - // } - // if (newAVL.size !== uniques) { - // throw new Error('elements not inserted properly') - // } - // const findTestSize = Math.floor(Math.random() * uniques) - // for (i = 0; i < findTestSize; i++) { - // j = Math.floor(Math.random() * uniques) - // if (!newAVL.find(array[j])) { - // throw new Error('inserted elements not found') - // } - // } - // const deleteTestSize = Math.floor(uniques * Math.random()) - // for (i = 0; i < deleteTestSize; i++) { - // j = Math.floor(Math.random() * uniques) - // temp = array[j] - // if (newAVL.find(temp)) { - // if (!newAVL.remove(temp)) { - // throw new Error('delete not working properly') - // } - // } - // } - // })() - - export { AVLTree } - \ No newline at end of file +/** + * A utility class for comparator + * A comparator is expected to have following structure + * + * comp(a, b) RETURN < 0 if a < b + * RETURN > 0 if a > b + * MUST RETURN 0 if a == b + */ +let utils; +(function (_utils) { + function comparator() { + return function (v1, v2) { + if (v1 < v2) return -1 + if (v2 < v1) return 1 + return 0 + } + } + _utils.comparator = comparator +})(utils || (utils = {})) + +/** + * @constructor + * A class for AVL Tree + * @argument comp - A function used by AVL Tree For Comparison + * 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() + + /** @public root of the AVL Tree */ + this.root = null + /** @public number of elements in AVL Tree */ + this.size = 0 + } + + // creates new Node Object + const Node = function (val) { + this._val = val + this._left = null + this._right = null + this._height = 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) + + // 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 + } + + // check if tree is balanced else balance it for insertion + const insertBalance = function (node, _val, balanceFactor) { + if (balanceFactor > 1 && _val < node._left._val) { + return rightRotate(node) // Left Left Case + } + if (balanceFactor < 1 && _val > node._right._val) { + return leftRotate(node) // Right Right Case + } + if (balanceFactor > 1 && _val > node._left._val) { + node._left = leftRotate(node._left) // Left Right Case + return rightRotate(node) + } + node._right = rightRotate(node._right) + return leftRotate(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) // 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) + } + 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) + } + + // 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) + } + } 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) + 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) + } + + /* 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 +}()) + +/** + * A Code for Testing the AVLTree + */ +// (function test () { +// const newAVL = new AVLTree() +// const size = Math.floor(Math.random() * 1000000) +// let uniques = 0 +// let i, temp, j +// const array = [] +// for (i = 0; i < size; i++) { +// temp = Math.floor(Math.random() * Number.MAX_VALUE) +// if (newAVL.add(temp)) { +// uniques++ +// array.push(temp) +// } +// } +// if (newAVL.size !== uniques) { +// throw new Error('elements not inserted properly') +// } +// const findTestSize = Math.floor(Math.random() * uniques) +// for (i = 0; i < findTestSize; i++) { +// j = Math.floor(Math.random() * uniques) +// if (!newAVL.find(array[j])) { +// throw new Error('inserted elements not found') +// } +// } +// const deleteTestSize = Math.floor(uniques * Math.random()) +// for (i = 0; i < deleteTestSize; i++) { +// j = Math.floor(Math.random() * uniques) +// temp = array[j] +// if (newAVL.find(temp)) { +// if (!newAVL.remove(temp)) { +// throw new Error('delete not working properly') +// } +// } +// } +// })() + +export { AVLTree } diff --git a/Data-Structures/Tree/test/AVLTree.test.js b/Data-Structures/Tree/test/AVLTree.test.js new file mode 100644 index 0000000000..bf8c8186c7 --- /dev/null +++ b/Data-Structures/Tree/test/AVLTree.test.js @@ -0,0 +1,32 @@ +import { AVLTree } from '../AVLTree' + +describe('AVLTree Implementation: ', () => { + const avlTree = new AVLTree(); + const size = Math.floor(Math.random() * 10); + const dataList = []; + + beforeAll(() => { + for (let i = 0; i < size; i++) { + const insertedData = Math.floor(Math.random() * Number.MAX_VALUE) + if (avlTree.add(insertedData)) { + dataList.push(insertedData); + } + } + }) + + it('checks if element is inserted properly', () => { + expect(dataList.length).toEqual(avlTree.size); + }) + + it('search if inserted element is present', () => { + dataList.forEach(data => { + expect(avlTree.find(data)).toBeTruthy(); + }) + }) + + it('deletes the inserted element', () => { + const deleteElement = dataList[Math.floor(Math.random() * size)]; + expect(avlTree.remove(deleteElement)).toBeTruthy(); + }) +}) + From 7a01994338199467594e018fcd833548b80f69c2 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 16 Feb 2022 09:21:07 +0000 Subject: [PATCH 3/5] Auto-update DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 46aa5907c6..927b3b1bde 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -255,6 +255,7 @@ * [UnionFind](https://github.com/TheAlgorithms/Javascript/blob/master/Search/UnionFind.js) ## Sorts + * [AlphaNumericalSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/AlphaNumericalSort.js) * [BeadSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BeadSort.js) * [BogoSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BogoSort.js) * [BubbleSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BubbleSort.js) From e9facac864933084f2a8e7b23be2780f5f12a0a5 Mon Sep 17 00:00:00 2001 From: Rahul Raj Date: Wed, 16 Feb 2022 20:43:18 +0530 Subject: [PATCH 4/5] Change in logic for data list --- Data-Structures/Tree/test/AVLTree.test.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Data-Structures/Tree/test/AVLTree.test.js b/Data-Structures/Tree/test/AVLTree.test.js index bf8c8186c7..d9834eeccc 100644 --- a/Data-Structures/Tree/test/AVLTree.test.js +++ b/Data-Structures/Tree/test/AVLTree.test.js @@ -2,16 +2,15 @@ import { AVLTree } from '../AVLTree' describe('AVLTree Implementation: ', () => { const avlTree = new AVLTree(); - const size = Math.floor(Math.random() * 10); const dataList = []; + const demoData = [1,4,6,22,7,99,4,66,77,98]; beforeAll(() => { - for (let i = 0; i < size; i++) { - const insertedData = Math.floor(Math.random() * Number.MAX_VALUE) - if (avlTree.add(insertedData)) { - dataList.push(insertedData); + demoData.forEach(item => { + if (avlTree.add(item)) { + dataList.push(item); } - } + }) }) it('checks if element is inserted properly', () => { @@ -19,13 +18,13 @@ describe('AVLTree Implementation: ', () => { }) it('search if inserted element is present', () => { - dataList.forEach(data => { + demoData.forEach(data => { expect(avlTree.find(data)).toBeTruthy(); }) }) it('deletes the inserted element', () => { - const deleteElement = dataList[Math.floor(Math.random() * size)]; + const deleteElement = dataList[3]; expect(avlTree.remove(deleteElement)).toBeTruthy(); }) }) From bd9481912db696681ad448ab715c6603bde0a1f4 Mon Sep 17 00:00:00 2001 From: Rahul Raj Date: Thu, 17 Feb 2022 12:04:56 +0530 Subject: [PATCH 5/5] Style fix based on standard.js --- Data-Structures/Tree/AVLTree.js | 4 +-- Data-Structures/Tree/test/AVLTree.test.js | 41 +++++++++++------------ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Data-Structures/Tree/AVLTree.js b/Data-Structures/Tree/AVLTree.js index 0cb7f8e8f3..d2b34362c0 100644 --- a/Data-Structures/Tree/AVLTree.js +++ b/Data-Structures/Tree/AVLTree.js @@ -15,7 +15,7 @@ */ let utils; (function (_utils) { - function comparator() { + function comparator () { return function (v1, v2) { if (v1 < v2) return -1 if (v2 < v1) return 1 @@ -32,7 +32,7 @@ let utils; * If no argument is sent it uses utils.comparator */ const AVLTree = (function () { - function _avl(comp) { + function _avl (comp) { /** @public comparator function */ this._comp = undefined this._comp = comp !== undefined ? comp : utils.comparator() diff --git a/Data-Structures/Tree/test/AVLTree.test.js b/Data-Structures/Tree/test/AVLTree.test.js index d9834eeccc..64cdd3ff48 100644 --- a/Data-Structures/Tree/test/AVLTree.test.js +++ b/Data-Structures/Tree/test/AVLTree.test.js @@ -1,31 +1,30 @@ import { AVLTree } from '../AVLTree' describe('AVLTree Implementation: ', () => { - const avlTree = new AVLTree(); - const dataList = []; - const demoData = [1,4,6,22,7,99,4,66,77,98]; + const avlTree = new AVLTree() + const dataList = [] + const demoData = [1, 4, 6, 22, 7, 99, 4, 66, 77, 98] - beforeAll(() => { - demoData.forEach(item => { - if (avlTree.add(item)) { - dataList.push(item); - } - }) + beforeAll(() => { + demoData.forEach(item => { + if (avlTree.add(item)) { + dataList.push(item) + } }) + }) - it('checks if element is inserted properly', () => { - expect(dataList.length).toEqual(avlTree.size); - }) + it('checks if element is inserted properly', () => { + expect(dataList.length).toEqual(avlTree.size) + }) - it('search if inserted element is present', () => { - demoData.forEach(data => { - expect(avlTree.find(data)).toBeTruthy(); - }) + it('search if inserted element is present', () => { + demoData.forEach(data => { + expect(avlTree.find(data)).toBeTruthy() }) + }) - it('deletes the inserted element', () => { - const deleteElement = dataList[3]; - expect(avlTree.remove(deleteElement)).toBeTruthy(); - }) + it('deletes the inserted element', () => { + const deleteElement = dataList[3] + expect(avlTree.remove(deleteElement)).toBeTruthy() + }) }) -