diff --git a/.gitignore b/.gitignore index 6fee6d3a..2458e8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea/* -*.log \ No newline at end of file +*.log +node_modules +coverage diff --git a/README.md b/README.md index 222adb3a..64771d99 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,21 @@ Learning JavaScript Data Structures and Algorithms Source code of **Learning JavaScript Data Structures and Algorithms** book. +| 1st edition | 2nd edition | +| ------------- |:-------------:| +|  |  | +| [Book link](http://amzn.to/1Y1OWPx)| [Book link](http://amzn.to/1TSkcA1)| + Book link - first edition: - [Packt](https://www.packtpub.com/application-development/learning-javascript-data-structures-and-algorithms) - - [Amazon](http://www.amazon.com/gp/product/1783554878/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1783554878&linkCode=as2&tag=loiagron-20&linkId=7VBQ7OMJ47XY7MUV) + - [Amazon](http://amzn.to/1Y1OWPx) + - [Chinese version](http://www.ituring.com.cn/book/1613) + - [Korean version](http://www.acornpub.co.kr/book/javascript-data-structure) + +Book link - second edition: + - [Packt](https://www.packtpub.com/web-development/learning-javascript-data-structures-and-algorithms-second-edition) + - [Amazon](http://amzn.to/1TSkcA1) + - [Brazilian Portuguese version](https://novatec.com.br/livros/estruturas-de-dados-algoritmos-em-javascript/) ### List of Chapters: @@ -16,12 +28,11 @@ Book link - first edition: * 05: [Linked Lists](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter05) * 06: [Sets](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter06) * 07: [Dictionaries and Hashes](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter07) -* 08: Trees -* 09: Graphs -* 10: Sorting and searching algorithms -* 11: Pattern of algorithms -* 12: More about algorithms -* 13: Functional programming and data structures +* 08: [Trees](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter08) +* 09: [Graphs](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter09) +* 10: [Sorting and searching algorithms](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter10) +* 11: [Pattern of algorithms](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter11) +* 12: [Algorithm Complexity](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter12) ### First Edition source code: diff --git a/chapter01/14-ES6ParameterHandling.js b/chapter01/14-ES6ParameterHandling.js index 706c2059..af23585c 100644 --- a/chapter01/14-ES6ParameterHandling.js +++ b/chapter01/14-ES6ParameterHandling.js @@ -14,7 +14,7 @@ function sum2 (x, y, z) { z = 3; return x + y + z; }; -console.log(sum2(4,2)); //outpus 10 +console.log(sum2(4,2)); //outpus 9 //******* EcmaScript 6: spread operator ('...') var params = [3, 4, 5]; @@ -30,8 +30,8 @@ function restParamaterFunction (x, y, ...a) { console.log(restParamaterFunction(1, 2, "hello", true, 7)); // outputs 9; //code above is the same as ES5: -function restParamaterFunction (x, y) { +function restParamaterFunction2 (x, y) { var a = Array.prototype.slice.call(arguments, 2); return (x + y) * a.length; }; -console.log(restParamaterFunction2(1, 2, "hello", true, 7)); \ No newline at end of file +console.log(restParamaterFunction2(1, 2, "hello", true, 7)); diff --git a/chapter02/06-ES6Methods.js b/chapter02/06-ES6Methods.js index 60468aa4..bf4eb36a 100644 --- a/chapter02/06-ES6Methods.js +++ b/chapter02/06-ES6Methods.js @@ -40,7 +40,7 @@ console.log(aKeys.next()); // {value: 1, done: false } console.log(aKeys.next()); // {value: 2, done: false } console.log('Array.values'); -//let aValues = numbers.values(); +let aValues = numbers.values(); console.log(aValues.next()); // {value: 1, done: false } done false means iterator has more values console.log(aValues.next()); // {value: 2, done: false } console.log(aValues.next()); // {value: 3, done: false } diff --git a/chapter04/03-PriorityQueue.js b/chapter04/03-PriorityQueue.js index f9071ddc..3b029e4d 100644 --- a/chapter04/03-PriorityQueue.js +++ b/chapter04/03-PriorityQueue.js @@ -50,7 +50,5 @@ let priorityQueue = new PriorityQueue(); priorityQueue.enqueue("John", 2); priorityQueue.enqueue("Jack", 1); priorityQueue.enqueue("Camila", 1); -priorityQueue.enqueue("Maxwell", 2); -priorityQueue.enqueue("Ana", 3); priorityQueue.print(); diff --git a/chapter05/05-CircularLinkedList.js b/chapter05/05-CircularLinkedList.js index 5f05e85f..c3151148 100644 --- a/chapter05/05-CircularLinkedList.js +++ b/chapter05/05-CircularLinkedList.js @@ -46,16 +46,22 @@ function CircularLinkedList() { index = 0; if (position === 0){ //add on first position - - node.next = current; - - //update last element - while(current.next !== head){ //last element will be head instead of NULL - current = current.next; + + if(!head){ // if no node in list + head = node; + node.next = head; + }else{ + node.next = current; + + //update last element + while(current.next !== head){ //last element will be head instead of NULL + current = current.next; + } + + head = node; + current.next = head; } - - head = node; - current.next = head; + } else { while (index++ < position){ @@ -180,4 +186,5 @@ function CircularLinkedList() { this.print = function(){ console.log(this.toString()); }; -} \ No newline at end of file +} + diff --git a/chapter05/05-CircularLinkedList2.js b/chapter05/05-CircularLinkedList2.js index 13f36665..6f7574ef 100644 --- a/chapter05/05-CircularLinkedList2.js +++ b/chapter05/05-CircularLinkedList2.js @@ -58,15 +58,18 @@ let CircularLinkedList2 = (function () { if (position === 0) { //add on first position - node.next = current; - - //update last element - while (current.next !== this.getHead()) { //last element will be head instead of NULL - current = current.next; - } - - head.set(this, node); - current.next = this.getHead(); + if(!this.getHead()) { // if no node in list + head.set(this, node); + node.next = this.getHead(); + } else { + node.next = current; + //update last element + while(current.next !== this.getHead()) { //last element will be head instead of NULL + current = current.next; + } + head.set(this, node); + current.next = this.getHead(); + } } else { while (index++ < position) { @@ -133,8 +136,8 @@ let CircularLinkedList2 = (function () { remove(element) { - let index = indexOf(element); - return removeAt(index); + let index = this.indexOf(element); + return this.removeAt(index); } indexOf(element) { @@ -198,4 +201,4 @@ let CircularLinkedList2 = (function () { } } return CircularLinkedList2; -})(); \ No newline at end of file +})(); diff --git a/chapter07/02-UsingDictionaries.js b/chapter07/02-UsingDictionaries.js index 3ec30d4b..dc0bf258 100644 --- a/chapter07/02-UsingDictionaries.js +++ b/chapter07/02-UsingDictionaries.js @@ -11,9 +11,9 @@ console.log(dictionary.keys()); //outputs ["Gandalf", "John", "Tyrion"] console.log(dictionary.values()); //outputs ["gandalf@email.com", "johnsnow@email.com", "tyrion@email.com"] console.log(dictionary.get('Tyrion')); //outputs tyrion@email.com -dictionary.delete(‘John'); +dictionary.delete('John'); console.log(dictionary.keys()); //outputs ["Gandalf", "Tyrion"] console.log(dictionary.values()); //outputs ["gandalf@email.com", "tyrion@email.com"] -console.log(dictionary.getItems()); //Object {Gandalf: "gandalf@email.com", Tyrion: "tyrion@email.com"} \ No newline at end of file +console.log(dictionary.getItems()); //Object {Gandalf: "gandalf@email.com", Tyrion: "tyrion@email.com"} diff --git a/chapter07/07-HashCollisionLinearProbing.js b/chapter07/07-HashCollisionLinearProbing.js index 74fdbac5..4b1172be 100644 --- a/chapter07/07-HashCollisionLinearProbing.js +++ b/chapter07/07-HashCollisionLinearProbing.js @@ -46,13 +46,22 @@ function HashLinearProbing(){ return table[position].value; } else { var index = ++position; - while (table[index] === undefined || table[index].key !== key){ + while (table[index] !== undefined && (table[index] && table[index].key !== key)){ index++; } - if (table[index].key === key) { + if (table[index] && table[index].key === key) { return table[index].value; } } + } else { //search for possible deleted value + var index = ++position; + while (table[index] == undefined || index == table.length || + (table[index] !== undefined && table[index] && table[index].key !== key)){ + index++; + } + if (table[index] && table[index].key === key) { + return table[index].value; + } } return undefined; }; @@ -82,4 +91,4 @@ function HashLinearProbing(){ } } }; -} \ No newline at end of file +} diff --git a/chapter07/08-UsingHashCollisionLinearProbing.js b/chapter07/08-UsingHashCollisionLinearProbing.js index 902384ee..36a33e61 100644 --- a/chapter07/08-UsingHashCollisionLinearProbing.js +++ b/chapter07/08-UsingHashCollisionLinearProbing.js @@ -26,4 +26,12 @@ console.log('**** Remove **** '); hashLinearProbing.remove('Gandalf'); console.log(hashLinearProbing.get('Gandalf')); +hashLinearProbing.print(); + +console.log('**** Remove Test 2 **** '); +console.log('Removing Jonathan', hashLinearProbing.remove('Jonathan')); +console.log('**** Print **** '); +hashLinearProbing.print(); +console.log('Get Jamie', hashLinearProbing.get('Jamie')); +console.log('**** Print **** '); hashLinearProbing.print(); \ No newline at end of file diff --git a/chapter08/02-UsingBinarySearchTree.js b/chapter08/02-UsingBinarySearchTree.js index 3caef17c..eb139837 100644 --- a/chapter08/02-UsingBinarySearchTree.js +++ b/chapter08/02-UsingBinarySearchTree.js @@ -49,4 +49,4 @@ tree.remove(15); tree.inOrderTraverse(printNode); console.log('********* raw data structure ***********'); -console.log(tree.getRoot()); \ No newline at end of file +console.log(tree.getRoot()); diff --git a/chapter08/03-AVLTree.js b/chapter08/03-AVLTree.js index e69de29b..2eed4f3e 100644 --- a/chapter08/03-AVLTree.js +++ b/chapter08/03-AVLTree.js @@ -0,0 +1,149 @@ +function AVLTree() { + + var Node = function(key){ + this.key = key; + this.left = null; + this.right = null; + }; + + var root = null; + + this.getRoot = function(){ + return root; + }; + + var heightNode = function(node) { + if (node === null) { + return -1; + } else { + return Math.max(heightNode(node.left), heightNode(node.right)) + 1; + } + }; + + var rotationLL = function(node) { + var tmp = node.left; + node.left = tmp.right; + tmp.right = node; + + return tmp; + }; + + var rotationRR = function(node) { + var tmp = node.right; + node.right = tmp.left; + tmp.left = node; + + return tmp; + }; + + var rotationLR = function(node) { + node.left = rotationRR(node.left); + return rotationLL(node); + }; + + var rotationRL = function(node) { + node.right = rotationLL(node.right); + return rotationRR(node); + }; + + var insertNode = function(node, element) { + + if (node === null) { + node = new Node(element); + + } else if (element < node.key) { + + node.left = insertNode(node.left, element); + + if (node.left !== null) { + + if ((heightNode(node.left) - heightNode(node.right)) > 1){ + if (element < node.left.key){ + node = rotationLL(node); + } else { + node = rotationLR(node); + } + } + } + } else if (element > node.key) { + + node.right = insertNode(node.right, element); + + if (node.right !== null) { + + if ((heightNode(node.right) - heightNode(node.left)) > 1){ + + if (element > node.right.key){ + node = rotationRR(node); + } else { + node = rotationRL(node); + } + } + } + } + + return node; + }; + + this.insert = function(element) { + root = insertNode(root, element); + }; + + var parentNode; + var nodeToBeDeleted; + + var removeNode = function(node, element) { + if (node === null) { + return null; + } + parentNode = node; + + if (element < node.key) { + node.left = removeNode(node.left, element); + } else { + nodeToBeDeleted = node; + node.right = removeNode(node.right, element); + } + + if (node === parentNode) { //remove node + if (nodeToBeDeleted !== null && element === nodeToBeDeleted.key) { + if (nodeToBeDeleted === parentNode) { + node = node.left; + } else { + var tmp = nodeToBeDeleted.key; + nodeToBeDeleted.key = parentNode.key; + parentNode.key = tmp; + node = node.right; + } + } + } else { //do balancing + + if (node.left === undefined) node.left = null; + if (node.right === undefined) node.right = null; + + if ((heightNode(node.left) - heightNode(node.right)) === 2) { + if (element < node.left.key) { + node = rotationLR(node); + } else { + node = rotationLL(node); + } + } + + if ((heightNode(node.right) - heightNode(node.left)) === 2) { + if (element > node.right.key) { + node = rotationRL(node); + } else { + node = rotationRR(node); + } + } + } + + return node; + }; + + this.remove = function(element) { + parentNode = null; + nodeToBeDeleted = null; + root = removeNode(root, element); + }; +} \ No newline at end of file diff --git a/chapter08/04-UsingAVLTree.html b/chapter08/04-UsingAVLTree.html index f7ce18b0..fda15f71 100644 --- a/chapter08/04-UsingAVLTree.html +++ b/chapter08/04-UsingAVLTree.html @@ -5,7 +5,7 @@