merge: Improving the coding standard for AvLTree Data Structure (#882)

* Improving the coding standard for AvLTree Data Structure

* Test case creation for AVLTree

~ Created test cases for AVL Tree
~ Indentation fix for AVLTree.js

* Auto-update DIRECTORY.md

* Change in logic for data list

* Style fix based on standard.js

Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
Rahul Raj
2022-02-17 14:08:26 +05:30
committed by GitHub
parent 6bd2ac682d
commit c9701e8a4c
2 changed files with 90 additions and 67 deletions

View File

@ -17,13 +17,9 @@ let utils;
(function (_utils) { (function (_utils) {
function comparator () { function comparator () {
return function (v1, v2) { return function (v1, v2) {
if (v1 < v2) { if (v1 < v2) return -1
return -1 if (v2 < v1) return 1
} else if (v2 < v1) { return 0
return 1
} else {
return 0
}
} }
} }
_utils.comparator = comparator _utils.comparator = comparator
@ -39,16 +35,14 @@ const AVLTree = (function () {
function _avl (comp) { function _avl (comp) {
/** @public comparator function */ /** @public comparator function */
this._comp = undefined this._comp = undefined
if (comp !== undefined) { this._comp = comp !== undefined ? comp : utils.comparator()
this._comp = comp
} else {
this._comp = utils.comparator()
}
/** @public root of the AVL Tree */ /** @public root of the AVL Tree */
this.root = null this.root = null
/** @public number of elements in AVL Tree */ /** @public number of elements in AVL Tree */
this.size = 0 this.size = 0
} }
// creates new Node Object // creates new Node Object
const Node = function (val) { const Node = function (val) {
this._val = val this._val = val
@ -56,95 +50,103 @@ const AVLTree = (function () {
this._right = null this._right = null
this._height = 1 this._height = 1
} }
// get height of a node // get height of a node
const getH = function (node) { const getHeight = function (node) {
if (node == null) { return 0 } if (node == null) { return 0 }
return node._height return node._height
} }
// height difference or balance factor of a node // height difference or balance factor of a node
const getHDiff = function (node) { const getHeightDifference = function (node) {
if (node == null) { return 0 } else { return getH(node._left) - getH(node._right) } return node == null ? 0 : getHeight(node._left) - getHeight(node._right)
} }
// update height of a node based on children's heights // update height of a node based on children's heights
const updateH = function (node) { const updateHeight = function (node) {
if (node == null) { if (node == null) { return }
return node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
}
node._height = Math.max(getH(node._left), getH(node._right)) + 1
} }
// Helper: To check if the balanceFactor is valid
const isValidBalanceFactor = (balanceFactor) => [0, 1, -1].includes(balanceFactor)
// rotations of AVL Tree // rotations of AVL Tree
const leftRotate = function (node) { const leftRotate = function (node) {
const temp = node._right const temp = node._right
node._right = temp._left node._right = temp._left
temp._left = node temp._left = node
updateH(node) updateHeight(node)
updateH(temp) updateHeight(temp)
return temp return temp
} }
const rightRotate = function (node) { const rightRotate = function (node) {
const temp = node._left const temp = node._left
node._left = temp._right node._left = temp._right
temp._right = node temp._right = node
updateH(node) updateHeight(node)
updateH(temp) updateHeight(temp)
return temp return temp
} }
// check if tree is balanced else balance it for insertion // check if tree is balanced else balance it for insertion
const insertBalance = function (node, _val, balanceFactor) { const insertBalance = function (node, _val, balanceFactor) {
if (balanceFactor > 1 && _val < node._left._val) { if (balanceFactor > 1 && _val < node._left._val) {
return rightRotate(node) // Left Left Case return rightRotate(node) // Left Left Case
} else if (balanceFactor < 1 && _val > node._right._val) { }
if (balanceFactor < 1 && _val > node._right._val) {
return leftRotate(node) // Right Right Case return leftRotate(node) // Right Right Case
} else if (balanceFactor > 1 && _val > node._left._val) { }
if (balanceFactor > 1 && _val > node._left._val) {
node._left = leftRotate(node._left) // Left Right Case node._left = leftRotate(node._left) // Left Right Case
return rightRotate(node) return rightRotate(node)
} }
node._right = rightRotate(node._right) node._right = rightRotate(node._right)
return leftRotate(node) return leftRotate(node)
} }
// check if tree is balanced after deletion // check if tree is balanced after deletion
const delBalance = function (node) { const delBalance = function (node) {
const balanceFactor1 = getHDiff(node) const balanceFactor1 = getHeightDifference(node)
if (balanceFactor1 === 0 || balanceFactor1 === 1 || balanceFactor1 === -1) { if (isValidBalanceFactor(balanceFactor1)) {
return node return node
} }
if (balanceFactor1 > 1) { if (balanceFactor1 > 1) {
if (getHDiff(node._left) >= 0) { if (getHeightDifference(node._left) >= 0) {
return rightRotate(node) // Left Left return rightRotate(node) // Left Left
} }
node._left = leftRotate(node._left) node._left = leftRotate(node._left)
return rightRotate(node) // Left Right return rightRotate(node) // Left Right
} }
if (getHDiff(node._right) > 0) { if (getHeightDifference(node._right) > 0) {
node._right = rightRotate(node._right) node._right = rightRotate(node._right)
return leftRotate(node) // Right Left return leftRotate(node) // Right Left
} }
return leftRotate(node) // Right Right return leftRotate(node) // Right Right
} }
// implement avl tree insertion // implement avl tree insertion
const insert = function (root, val, tree) { const insert = function (root, val, tree) {
if (root == null) { if (root == null) {
tree.size++ tree.size++
return new Node(val) return new Node(val)
} else if (tree._comp(root._val, val) < 0) { }
if (tree._comp(root._val, val) < 0) {
root._right = insert(root._right, val, tree) root._right = insert(root._right, val, tree)
} else if (tree._comp(root._val, val) > 0) { } else if (tree._comp(root._val, val) > 0) {
root._left = insert(root._left, val, tree) root._left = insert(root._left, val, tree)
} else { } else {
return root return root
} }
updateH(root) updateHeight(root)
const balanceFactor = getHDiff(root) const balanceFactor = getHeightDifference(root)
if (balanceFactor === 0 || balanceFactor === 1 || balanceFactor === -1) { return isValidBalanceFactor(balanceFactor) ? root : insertBalance(root, val, balanceFactor)
return root
}
return insertBalance(root, val, balanceFactor)
} }
// delete a element
const del = function (root, _val, tree) { // delete am element
if (root == null) { const deleteElement = function (root, _val, tree) {
return root if (root == null) { return root }
} else if (tree._comp(root._val, _val) === 0) { // key found case if (tree._comp(root._val, _val) === 0) { // key found case
if (root._left === null && root._right === null) { if (root._left === null && root._right === null) {
root = null root = null
tree.size-- tree.size--
@ -160,29 +162,29 @@ const AVLTree = (function () {
temp = temp._left temp = temp._left
} }
root._val = temp._val root._val = temp._val
root._right = del(root._right, temp._val, tree) root._right = deleteElement(root._right, temp._val, tree)
} }
} else { } else {
if (tree._comp(root._val, _val) < 0) { if (tree._comp(root._val, _val) < 0) {
root._right = del(root._right, _val, tree) root._right = deleteElement(root._right, _val, tree)
} else { } else {
root._left = del(root._left, _val, tree) root._left = deleteElement(root._left, _val, tree)
} }
} }
updateH(root) updateHeight(root)
root = delBalance(root) root = delBalance(root)
return root return root
} }
// search tree for a element // search tree for a element
const search = function (root, val, tree) { const searchAVLTree = function (root, val, tree) {
if (root == null) { if (root == null) { return null }
return null if (tree._comp(root._val, val) === 0) {
} else if (tree._comp(root._val, val) === 0) {
return root return root
} else if (tree._comp(root._val, val) < 0) {
return search(root._right, val, tree)
} }
return search(root._left, val, tree) if (tree._comp(root._val, val) < 0) {
return searchAVLTree(root._right, val, tree)
}
return searchAVLTree(root._left, val, tree)
} }
/* Public Functions */ /* Public Functions */
@ -196,10 +198,7 @@ const AVLTree = (function () {
_avl.prototype.add = function (_val) { _avl.prototype.add = function (_val) {
const prevSize = this.size const prevSize = this.size
this.root = insert(this.root, _val, this) this.root = insert(this.root, _val, this)
if (this.size === prevSize) { return this.size !== prevSize
return false
}
return true
} }
/** /**
* TO check is a particular element exists or not * TO check is a particular element exists or not
@ -207,11 +206,8 @@ const AVLTree = (function () {
* @returns {Boolean} exists or not * @returns {Boolean} exists or not
*/ */
_avl.prototype.find = function (_val) { _avl.prototype.find = function (_val) {
const temp = search(this.root, _val, this) const temp = searchAVLTree(this.root, _val, this)
if (temp != null) { return temp != null
return true
}
return false
} }
/** /**
* *
@ -222,11 +218,8 @@ const AVLTree = (function () {
*/ */
_avl.prototype.remove = function (_val) { _avl.prototype.remove = function (_val) {
const prevSize = this.size const prevSize = this.size
this.root = del(this.root, _val, this) this.root = deleteElement(this.root, _val, this)
if (prevSize === this.size) { return prevSize !== this.size
return false
}
return true
} }
return _avl return _avl
}()) }())

View File

@ -0,0 +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]
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('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()
})
})