diff --git a/src/_DataStructures_/Queue/Queue.test.js b/src/_DataStructures_/Queue/Queue.test.js index 999883f0..fe1c502a 100644 --- a/src/_DataStructures_/Queue/Queue.test.js +++ b/src/_DataStructures_/Queue/Queue.test.js @@ -69,14 +69,5 @@ describe('Data Structure : Queue', () => { queue.destroy(); expect(queue.length()).toEqual(0); }); - - it('Override and throw error for other LL methods', () => { - expect(() => { queue.addAtBeginning(); }).toThrowError('Not Allowed'); - expect(() => { queue.addAt(); }).toThrowError('Not Allowed'); - expect(() => { queue.removeFromEnd(); }).toThrowError('Not Allowed'); - expect(() => { queue.getLast(); }).toThrowError('Not Allowed'); - expect(() => { queue.getAt(); }).toThrowError('Not Allowed'); - expect(() => { queue.removeAt(); }).toThrowError('Not Allowed'); - }); }); }); diff --git a/src/_DataStructures_/Queue/index.js b/src/_DataStructures_/Queue/index.js index 9056c130..0a0807df 100644 --- a/src/_DataStructures_/Queue/index.js +++ b/src/_DataStructures_/Queue/index.js @@ -1,56 +1,54 @@ -const { LinkedList: SinglyLinkedLists } = require('../LinkedList'); +const { LinkedList: SLL } = require('../LinkedList'); -class Queue extends SinglyLinkedLists { +class Queue { constructor() { - super(); - this.NotAllowed = 'Not Allowed'; + this.data = this.getStorage(); } - enqueue(data) { - return this.addAtEnd(data); + enqueue(element) { + this.data.enqueue(element); } dequeue() { - const node = this.removeFromBeginning(); - return node ? node.data : node; + return this.data.dequeue(); } peek() { - const node = this.getFirst(); - return node ? node.data : node; + return this.data.peek(); } length() { - return this.size; + return this.data.length(); } destroy() { - this.delete(); - } - - /** Override and throw error for other LL methods */ - addAtBeginning() { - throw new Error(this.NotAllowed); - } - - addAt() { - throw new Error(this.NotAllowed); - } - - removeFromEnd() { - throw new Error(this.NotAllowed); - } - - getLast() { - throw new Error(this.NotAllowed); - } - - getAt() { - throw new Error(this.NotAllowed); - } - - removeAt() { - throw new Error(this.NotAllowed); + return this.data.destroy(); + } + + // eslint-disable-next-line class-methods-use-this + getStorage() { + // encapsulating the internal implementation here + const storage = new SLL(); + + return { + enqueue(element) { + return storage.addAtEnd(element); + }, + dequeue() { + const node = storage.removeFromBeginning(); + return node ? node.data : node; + }, + peek() { + const node = storage.getFirst(); + return node ? node.data : node; + }, + length() { + return storage.size; + }, + destroy() { + storage.delete(); + }, + }; } } diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-insertion.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-insertion.test.js deleted file mode 100644 index 8ada776d..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-insertion.test.js +++ /dev/null @@ -1,68 +0,0 @@ -const BinarySearchTree = require('./index'); - -describe('Binary Search Tree', () => { - let bst; - let rootsLeftChild; - let rootsRightChild; - let rootsLeftChildsLeftChild; - let rootsLeftChildsRightChild; - let rootsRightChildsLeftChild; - let rootsRightChildsRightChild; - - describe('Creates a binary search tree', () => { - it('should create a bst with root 100', () => { - bst = new BinarySearchTree(100); - expect(bst.root.value).toEqual(100); - }); - - it('should add element 20 to the left of root node', () => { - bst.add(20); - rootsLeftChild = bst.root.leftChild; - expect(rootsLeftChild.value).toEqual(20); - }); - - it('should add element 500 to the right of root node', () => { - bst.add(500); - rootsRightChild = bst.root.rightChild; - expect(rootsRightChild.value).toEqual(500); - }); - - it('should add element 10 to the left of root"s left child', () => { - bst.add(10); - rootsLeftChildsLeftChild = bst.root.leftChild.leftChild; - expect(rootsLeftChildsLeftChild.value).toEqual(10); - }); - - it('should add element 30 to the right of root"s left child', () => { - bst.add(30); - rootsLeftChildsRightChild = bst.root.leftChild.rightChild; - expect(rootsLeftChildsRightChild.value).toEqual(30); - }); - - it('should add element 400 to the left of root"s right child', () => { - bst.add(400); - rootsRightChildsLeftChild = bst.root.rightChild.leftChild; - expect(rootsRightChildsLeftChild.value).toEqual(400); - }); - - it('should add element 600 to the right of root"s right child', () => { - bst.add(600); - rootsRightChildsRightChild = bst.root.rightChild.rightChild; - expect(rootsRightChildsRightChild.value).toEqual(600); - }); - }); - - describe('Check insertion was as expected', () => { - it('Inorder traversal of the created bst should be [ 10, 20, 30, 100, 400, 500, 600 ]', () => { - expect(bst.traverseInorder()).toEqual([10, 20, 30, 100, 400, 500, 600]); - }); - - it('Preorder traversal of the created bst should be [ 100, 20, 10, 30, 500, 400, 600 ]', () => { - expect(bst.traversePreorder()).toEqual([100, 20, 10, 30, 500, 400, 600]); - }); - - it('Postorder traversal of the created bst should be [ 10, 30, 20, 400, 600, 500, 100 ]', () => { - expect(bst.traversePostorder()).toEqual([10, 30, 20, 400, 600, 500, 100]); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-isEmpty.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-isEmpty.test.js deleted file mode 100644 index ec81fc88..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-isEmpty.test.js +++ /dev/null @@ -1,18 +0,0 @@ -const BinarySearchTree = require('./index'); - -describe('Binary Search Tree', () => { - describe('Is Empty', () => { - const bst = new BinarySearchTree(6); - const keys = [4, 9, 2, 5, 8, 12]; - keys.forEach(el => bst.add(el)); - it('should return False when BST is not empty', () => { - expect(bst.isEmpty()).toEqual(false); - }); - - it('should return True when BST is empty', () => { - keys.push(6); - keys.forEach(el => bst.remove(el)); - expect(bst.isEmpty()).toEqual(true); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-maximum.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-maximum.test.js deleted file mode 100644 index f00d0f5b..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-maximum.test.js +++ /dev/null @@ -1,18 +0,0 @@ -const BinarySearchTree = require('./index'); - -describe('Binary Search Tree', () => { - describe('Find maximum value in BST', () => { - const bst = new BinarySearchTree(6); - const keys = [4, 9, 2, 5, 8, 12]; - keys.forEach(el => bst.add(el)); - - it('It should expect maximum key', () => { - expect(bst.getMaximum()).toEqual(12); - }); - - it('It should expect new maximum key added in BST', () => { - bst.add(20); - expect(bst.getMaximum()).toEqual(20); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-minimum.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-minimum.test.js deleted file mode 100644 index 80793665..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-minimum.test.js +++ /dev/null @@ -1,18 +0,0 @@ -const BinarySearchTree = require('./index'); - -describe('Binary Search Tree', () => { - describe('It should Find the minimum value in BST', () => { - const bst = new BinarySearchTree(6); - const keys = [4, 9, 2, 5, 8, 12]; - keys.forEach(el => bst.add(el)); - - it('It should expect minimum key', () => { - expect(bst.getMinimum()).toEqual(2); - }); - - it('It should expect new minimum key added to BST', () => { - bst.add(1); - expect(bst.getMinimum()).toEqual(1); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-remove.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-remove.test.js deleted file mode 100644 index b357f82d..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-remove.test.js +++ /dev/null @@ -1,32 +0,0 @@ -const BST = require('.'); - -describe('Data Structure : Binary Search Tree', () => { - it('Binary Search Tree should be a Class', () => { - expect(typeof BST.prototype.constructor).toEqual('function'); - }); - - describe('Binary Search Tree API', () => { - let bst = null; - - beforeEach(() => { - bst = new BST(5); - }); - - it('Should delete() an element from Binary Search Tree', () => { - bst.add(4); - bst.add(9); - bst.add(2); - bst.delete(bst.root, 4); - expect(bst.traverseInorder()).toEqual([2, 5, 9]); - bst.delete(bst.root, 2); - expect(bst.traverseInorder()).toEqual([5, 9]); - }); - - it('Should return NULL if root is empty', () => { - const bst2 = new BST(6); - bst2.remove(6); - bst2.remove(9); - expect(bst2.root).toEqual(null); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-search.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-search.test.js deleted file mode 100644 index 2558d0a6..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-search.test.js +++ /dev/null @@ -1,17 +0,0 @@ -const BinarySearchTree = require('./index'); - -describe('Binary Search Tree', () => { - describe('It should Find the key in BST', () => { - const bst = new BinarySearchTree(6); - const keys = [4, 9, 2, 5, 8, 12]; - keys.forEach(el => bst.add(el)); - - it('It should return true for 8', () => { - expect(bst.searchFor(8)).toEqual(true); - }); - - it('It should return false for 100', () => { - expect(bst.searchFor(100)).toEqual(false); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/bst-traversals.test.js b/src/_DataStructures_/Trees/BinarySearchTree/bst-traversals.test.js deleted file mode 100644 index 95a1d980..00000000 --- a/src/_DataStructures_/Trees/BinarySearchTree/bst-traversals.test.js +++ /dev/null @@ -1,34 +0,0 @@ -const BinarySearchTree = require('./index'); - -describe('Binary search tree traversals', () => { - let bst; - let preOrderTraversal, inOrderTraversal, postOrderTraversal; - - describe('Creates BST', () => { - // Creates BST - bst = new BinarySearchTree(6); - bst.add(4); - bst.add(9); - bst.add(2); - bst.add(5); - bst.add(8); - bst.add(12); - }); - - describe('BST traversals', () => { - it('should complete the Preorder traversal for the above created bst', () => { - preOrderTraversal = bst.traversePreorder(); - expect(preOrderTraversal).toEqual([6, 4, 2, 5, 9, 8, 12]); - }); - - it('should complete the Inorder traversal for the above created bst', () => { - inOrderTraversal = bst.traverseInorder(); - expect(inOrderTraversal).toEqual([2, 4, 5, 6, 8, 9, 12]); - }); - - it('should complete the Postorder traversal for the above created bst', () => { - postOrderTraversal = bst.traversePostorder(); - expect(postOrderTraversal).toEqual([2, 5, 4, 8, 12, 9, 6]); - }); - }); -}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/height-of-bst.test.js b/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/height-of-bst.test.js index 322172c9..f11f9455 100644 --- a/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/height-of-bst.test.js +++ b/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/height-of-bst.test.js @@ -15,15 +15,15 @@ describe('Binary search tree traversals', () => { describe('Check bst was created as expected', () => { it('Inorder traversal of the created bst should be [ 2, 4, 5, 6, 8, 9, 12 ]', () => { - expect(bst.traverseInorder()).toEqual([2, 4, 5, 6, 8, 9, 12]); + expect(bst.inorder()).toEqual([2, 4, 5, 6, 8, 9, 12]); }); it('Preorder traversal of the created bst should be [ 6, 4, 2, 5, 9, 8, 12 ]', () => { - expect(bst.traversePreorder()).toEqual([6, 4, 2, 5, 9, 8, 12]); + expect(bst.preorder()).toEqual([6, 4, 2, 5, 9, 8, 12]); }); it('Postorder traversal of the created bst should be [ 2, 5, 4, 8, 12, 9, 6 ]', () => { - expect(bst.traversePostorder()).toEqual([2, 5, 4, 8, 12, 9, 6]); + expect(bst.postorder()).toEqual([2, 5, 4, 8, 12, 9, 6]); }); }); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/index.js b/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/index.js index ad4f1ee7..809a6a65 100644 --- a/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/index.js +++ b/src/_DataStructures_/Trees/BinarySearchTree/height-of-bst/index.js @@ -27,7 +27,7 @@ function findHeightOfBST(root) { // myBST.add(10); // // console.log(myBST.root); -// console.log(myBST.traversePreorder()); +// console.log(myBST.preorder()); // console.log(findHeightOfBST(myBST.root)); module.exports = findHeightOfBST; diff --git a/src/_DataStructures_/Trees/BinarySearchTree/index.js b/src/_DataStructures_/Trees/BinarySearchTree/index.js index 5cd24103..1c96ed4f 100644 --- a/src/_DataStructures_/Trees/BinarySearchTree/index.js +++ b/src/_DataStructures_/Trees/BinarySearchTree/index.js @@ -1,199 +1,67 @@ -/* eslint-disable consistent-return */ const Node = require('./Node'); +const BSTUtils = require('./utils'); class BinarySearchTree { constructor(value) { + if (!value) throw new Error('Root node value required'); this.root = new Node(value); } - insert(root, value) { - if (root === null) { - const newNode = new Node(value); - // eslint-disable-next-line no-param-reassign - root = newNode; - return root; - } - - if (value < root.value) { - // eslint-disable-next-line no-param-reassign - root.leftChild = this.insert(root.leftChild, value); - return root; - } - if (value > root.value) { - // eslint-disable-next-line no-param-reassign - root.rightChild = this.insert(root.rightChild, value); - return root; - } - } - - preorder(root) { - /** returning an array so as to make testing easy */ - let arr = []; - if (root === null) return []; - arr.push(root.value); - - const left = this.preorder(root.leftChild); - arr = [...arr, ...left]; - - const right = this.preorder(root.rightChild); - arr = [...arr, ...right]; - return arr; - } - - inorder(root) { - /** left - root - right */ - if (root === null) return []; - let arr = []; - const left = this.inorder(root.leftChild); - arr = [...left, ...arr]; - - // print root - arr = [...arr, root.value]; - - const right = this.inorder(root.rightChild); - arr = [...arr, ...right]; - return arr; - } - - postorder(root) { - /** left - right - root */ - - if (root === null) return []; - let arr = []; - - const left = this.postorder(root.leftChild); - arr = [...left, ...arr]; - - const right = this.postorder(root.rightChild); - arr = [...arr, ...right]; - - return [...arr, root.value]; - } - - search(root, value) { - if (root === null) return false; - if (value === root.value) return true; - - if (value < root.value) { - return this.search(root.leftChild, value); - } - if (value > root.value) { - return this.search(root.rightChild, value); - } - } - - delete(root, value) { - if (root === null) { - return root; - } - - if (value > root.value) { - // eslint-disable-next-line no-param-reassign - root.rightChild = this.delete(root.rightChild, value); - } else if (value < root.value) { - // eslint-disable-next-line no-param-reassign - root.leftChild = this.delete(root.leftChild, value); - } else { - // found the node - if (root.leftChild === null) { - // there is a right sub-tree - return root.rightChild; - } - if (root.rightChild === null) { - // there is a left sub-tree - return root.leftChild; - } - /** - * the root contain 2 childs, we got 2 options: - * 1. We can either find the Node with minimum value at from the right sub-tree - * 2. Or, we can find the Node with maximum value from the left sub-tree - * - * I'm picking up 1 here - */ - const minRightNode = this.findMinNode(root.rightChild); - // eslint-disable-next-line no-param-reassign - root.value = minRightNode.value; - // eslint-disable-next-line no-param-reassign - root.rightChild = this.delete(root.rightChild, minRightNode.value); - return root; - } - return root; - } - - findMinNode(root) { - /** The minnimum values is the let most leaf node in BST */ - if (root.leftChild === null) return root; - return this.findMinNode(root.leftChild); - } - - findMaxNode(root) { - if (root.rightChild === null) return root; - return this.findMaxNode(root.rightChild); - } - isEmpty() { return this.root === null; } - /** Layered methods to simplify the BST API */ + /** Layered methods to simplify the BST API using utils under the hood */ add(value) { - return this.insert(this.root, value); + return BSTUtils.insert(this.root, value); } - traversePreorder() { - return this.preorder(this.root); + preorder() { + return BSTUtils.preorder(this.root, []); } - traversePostorder() { - return this.postorder(this.root); + postorder() { + return BSTUtils.postorder(this.root, []); } - traverseInorder() { - return this.inorder(this.root); + inorder() { + return BSTUtils.inorder(this.root, []); } - searchFor(value) { - return this.search(this.root, value); + search(value) { + return BSTUtils.search(this.root, value); } getMinimum() { - const minNode = this.findMinNode(this.root); + const minNode = BSTUtils.findMinNode(this.root); return minNode.value; } getMaximum() { - const maxNode = this.findMaxNode(this.root); + const maxNode = BSTUtils.findMaxNode(this.root); return maxNode.value; } remove(value) { - this.root = this.delete(this.root, value); + this.root = BSTUtils.delete(this.root, value); } } // const bst = new BinarySearchTree(6); -// console.log(bst.root); -// bst.add(4); -// bst.add(9); -// bst.add(2); -// bst.add(5); -// bst.add(8); -// bst.add(12); - -// console.log(bst.root); +// [4, 9, 2, 5, 8, 12].forEach(el => bst.add(el)); -// const preorder = bst.traversePreorder(); +// const preorder = bst.preorder(); // console.log('Preorder Traversal - ', preorder); -// const inorder = bst.traverseInorder(); +// const inorder = bst.inorder(); // console.log('Inorder Traversal - ', inorder); -// const postorder = bst.traversePostorder(); +// const postorder = bst.postorder(); // console.log('Postorder Traversal - ', postorder); // const search = 18; -// console.log(`Search for ${search}`, bst.searchFor(search)); +// console.log(`Search for ${search}`, bst.search(search)); // const minNode = bst.getMinimum(); // console.log('Minimum value =>', minNode); @@ -202,7 +70,7 @@ class BinarySearchTree { // console.log('Maximum value =>', maxNode); // bst.remove(4); -// console.log(bst.traversePreorder()); +// console.log(bst.preorder()); // console.log(bst.root); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/index.test.js b/src/_DataStructures_/Trees/BinarySearchTree/index.test.js new file mode 100644 index 00000000..5ec92ced --- /dev/null +++ b/src/_DataStructures_/Trees/BinarySearchTree/index.test.js @@ -0,0 +1,175 @@ +const BinarySearchTree = require('./index'); + +describe('Data Structure : Binary Search Tree', () => { + let bst; + let rootsLeftChild; + let rootsRightChild; + let rootsLeftChildsLeftChild; + let rootsLeftChildsRightChild; + let rootsRightChildsLeftChild; + let rootsRightChildsRightChild; + + it('Binary Search Tree should be a Class', () => { + expect(typeof BinarySearchTree.prototype.constructor).toEqual('function'); + }); + + describe('Creation of BST', () => { + it('Should create a BST with root 100', () => { + bst = new BinarySearchTree(100); + expect(bst.root.value).toEqual(100); + }); + + it('Should add element 20 to the left of root node', () => { + bst.add(20); + rootsLeftChild = bst.root.leftChild; + expect(rootsLeftChild.value).toEqual(20); + }); + + it('Should add element 500 to the right of root node', () => { + bst.add(500); + rootsRightChild = bst.root.rightChild; + expect(rootsRightChild.value).toEqual(500); + }); + + it('Should add element 10 to the left of root"s left child', () => { + bst.add(10); + rootsLeftChildsLeftChild = bst.root.leftChild.leftChild; + expect(rootsLeftChildsLeftChild.value).toEqual(10); + }); + + it('Should add element 30 to the right of root"s left child', () => { + bst.add(30); + rootsLeftChildsRightChild = bst.root.leftChild.rightChild; + expect(rootsLeftChildsRightChild.value).toEqual(30); + }); + + it("Should add element 400 to the left of root's right child", () => { + bst.add(400); + rootsRightChildsLeftChild = bst.root.rightChild.leftChild; + expect(rootsRightChildsLeftChild.value).toEqual(400); + }); + + it("Should add element 600 to the right of root's right child", () => { + bst.add(600); + rootsRightChildsRightChild = bst.root.rightChild.rightChild; + expect(rootsRightChildsRightChild.value).toEqual(600); + }); + }); + + describe('Check insertion was as expected', () => { + it('Inorder traversal of the created bst should be [ 10, 20, 30, 100, 400, 500, 600 ]', () => { + expect(bst.inorder()).toEqual([10, 20, 30, 100, 400, 500, 600]); + }); + + it('Preorder traversal of the created bst should be [ 100, 20, 10, 30, 500, 400, 600 ]', () => { + expect(bst.preorder()).toEqual([100, 20, 10, 30, 500, 400, 600]); + }); + + it('Postorder traversal of the created bst should be [ 10, 30, 20, 400, 600, 500, 100 ]', () => { + expect(bst.postorder()).toEqual([10, 30, 20, 400, 600, 500, 100]); + }); + }); + + describe('Check if BST `Is Empty`, find Min & Max in BST', () => { + const keys = [4, 9, 2, 5, 8, 12]; + + beforeEach(() => { + bst = new BinarySearchTree(6); + keys.forEach(el => bst.add(el)); + }); + + afterEach(() => { + if (bst.root) bst.root = null; + }); + + it('Should return `false` when BST is not empty', () => { + expect(bst.isEmpty()).toEqual(false); + }); + + it('Should return `true` when BST is empty', () => { + // remove all the nodes + keys.push(6); // head node + keys.forEach(e => bst.remove(e)); + expect(bst.isEmpty()).toEqual(true); + }); + + it('Should expect maximum key', () => { + expect(bst.getMaximum()).toEqual(12); + }); + + it('Should expect new maximum key added in BST', () => { + bst.add(20); + expect(bst.getMaximum()).toEqual(20); + }); + + it('Should expect minimum key', () => { + expect(bst.getMinimum()).toEqual(2); + }); + + it('Should expect new minimum key added to BST', () => { + bst.add(1); + expect(bst.getMinimum()).toEqual(1); + }); + }); + + describe('Remove Node in BST', () => { + beforeEach(() => { + bst = new BinarySearchTree(5); + }); + + it('Should delete() an element from Binary Search Tree', () => { + bst.add(4); + bst.add(9); + bst.add(2); + bst.remove(4); + expect(bst.inorder()).toEqual([2, 5, 9]); + bst.remove(2); + expect(bst.inorder()).toEqual([5, 9]); + }); + + it('Should return NULL if root is empty', () => { + const bst2 = new BinarySearchTree(6); + bst2.remove(6); + bst2.remove(9); + expect(bst2.root).toEqual(null); + }); + }); + + describe('Search value in BST', () => { + bst = new BinarySearchTree(6); + + it('Should return `true` for 8', () => { + [4, 9, 2, 5, 8, 12].forEach(el => bst.add(el)); + expect(bst.search(8)).toEqual(true); + }); + + it('Should return `false` for 100', () => { + expect(bst.search(100)).toEqual(false); + }); + }); + + describe('Traversals in BST', () => { + beforeEach(() => { + bst = new BinarySearchTree(6); + [4, 9, 2, 5, 8, 12].forEach(el => bst.add(el)); + }); + afterEach(() => { + if (bst.root) bst.root = null; + }); + + it('Should return the `Preorder Traversal` for given BST', () => { + const preOrderTraversal = bst.preorder(); + expect(preOrderTraversal).toEqual([6, 4, 2, 5, 9, 8, 12]); + }); + + it('Should return the `Inorder Traversal` for given BST', () => { + const inOrderTraversal = bst.inorder(); + expect(inOrderTraversal).toEqual([2, 4, 5, 6, 8, 9, 12]); + }); + + it('Should return the `Postorder Traversal` for given BST', () => { + const postOrderTraversal = bst.postorder(); + expect(postOrderTraversal).toEqual([2, 5, 4, 8, 12, 9, 6]); + }); + }); +}); diff --git a/src/_DataStructures_/Trees/BinarySearchTree/utils.js b/src/_DataStructures_/Trees/BinarySearchTree/utils.js new file mode 100644 index 00000000..a52f9191 --- /dev/null +++ b/src/_DataStructures_/Trees/BinarySearchTree/utils.js @@ -0,0 +1,112 @@ +const Node = require('./Node'); + +const utils = { + // eslint-disable-next-line consistent-return + insert(root, value) { + if (root === null) { + const newNode = new Node(value); + // eslint-disable-next-line no-param-reassign + root = newNode; + return root; + } + + if (value < root.value) { + // eslint-disable-next-line no-param-reassign + root.leftChild = this.insert(root.leftChild, value); + return root; + } + if (value > root.value) { + // eslint-disable-next-line no-param-reassign + root.rightChild = this.insert(root.rightChild, value); + return root; + } + }, + + preorder(root, array) { + if (root === null) return array; + array.push(root.value); + this.preorder(root.leftChild, array); + this.preorder(root.rightChild, array); + return array; + }, + + inorder(root, array) { + if (root === null) return array; + this.inorder(root.leftChild, array); + array.push(root.value); + this.inorder(root.rightChild, array); + return array; + }, + + postorder(root, array) { + if (root === null) return array; + this.postorder(root.leftChild, array); + this.postorder(root.rightChild, array); + array.push(root.value); + return array; + }, + + // eslint-disable-next-line consistent-return + search(root, value) { + if (root === null) return false; + if (value === root.value) return true; + + if (value < root.value) { + return this.search(root.leftChild, value); + } + if (value > root.value) { + return this.search(root.rightChild, value); + } + }, + + delete(root, value) { + if (root === null) { + return root; + } + + if (value > root.value) { + // eslint-disable-next-line no-param-reassign + root.rightChild = this.delete(root.rightChild, value); + } else if (value < root.value) { + // eslint-disable-next-line no-param-reassign + root.leftChild = this.delete(root.leftChild, value); + } else { + // found the node + if (root.leftChild === null) { + // there is a right sub-tree + return root.rightChild; + } + if (root.rightChild === null) { + // there is a left sub-tree + return root.leftChild; + } + /** + * the root contain 2 childs, we got 2 options: + * 1. We can either find the Node with minimum value at from the right sub-tree + * 2. Or, we can find the Node with maximum value from the left sub-tree + * + * I'm picking up 1 here + */ + const minRightNode = this.findMinNode(root.rightChild); + // eslint-disable-next-line no-param-reassign + root.value = minRightNode.value; + // eslint-disable-next-line no-param-reassign + root.rightChild = this.delete(root.rightChild, minRightNode.value); + return root; + } + return root; + }, + + findMinNode(root) { + /** The minnimum values is the let most leaf node in BST */ + if (root.leftChild === null) return root; + return this.findMinNode(root.leftChild); + }, + + findMaxNode(root) { + if (root.rightChild === null) return root; + return this.findMaxNode(root.rightChild); + }, +}; + +module.exports = utils; diff --git a/src/_DataStructures_/Trees/BinaryTree/index.js b/src/_DataStructures_/Trees/BinaryTree/index.js index 7cb032c4..296e763e 100644 --- a/src/_DataStructures_/Trees/BinaryTree/index.js +++ b/src/_DataStructures_/Trees/BinaryTree/index.js @@ -21,7 +21,7 @@ class BinaryTree { return root; } - traversePreorder(root) { + preorder(root) { let arr = []; if (root === null) return arr; @@ -29,18 +29,18 @@ class BinaryTree { arr.push(root.value); // push left node - const left = this.traversePreorder(root.leftChild); + const left = this.preorder(root.leftChild); arr = [...arr, ...left]; // push right node - const right = this.traversePreorder(root.rightChild); + const right = this.preorder(root.rightChild); arr = [...arr, ...right]; return arr; } preOrder() { - return this.traversePreorder(this.root); + return this.preorder(this.root); } } diff --git a/src/_Problems_/bfs-bst/index.js b/src/_Problems_/bfs-bst/index.js new file mode 100644 index 00000000..263d8290 --- /dev/null +++ b/src/_Problems_/bfs-bst/index.js @@ -0,0 +1,32 @@ +const BST = require('../../_DataStructures_/Trees/BinarySearchTree'); +const Queue = require('../../_DataStructures_/Queue'); + +function traverseBFS(root) { + let temp = root; + const arr = []; + const nodeQueue = new Queue(); + + if (root === null) { + return arr; + } + + while (temp !== null) { + arr.push(temp.value); + if (temp.leftChild) nodeQueue.enqueue(temp.leftChild); + if (temp.rightChild) nodeQueue.enqueue(temp.rightChild); + temp = nodeQueue.dequeue(); + } + return arr; +} + +const myBST = new BST(51); + +[10, 34, 32, 12, 90, 54, 61, 2, 71, 9].forEach(e => myBST.add(e)); + +const preOrderElements = myBST.preorder(); +const levelOrderElements = traverseBFS(myBST.root); + +// eslint-disable-next-line no-console +console.log(preOrderElements); +// eslint-disable-next-line no-console +console.log(levelOrderElements);