├── 02-chapter-Array ├── 02-chapter-Arrays.js └── readme.md ├── 03-chapter-List.js ├── 04-chapter-Stack ├── index.js ├── readme.md ├── stack.module.js └── test.js ├── 05-chapter-Queue ├── index.js ├── queue.module.js ├── readme.md └── test.js ├── 06-chapter-Linked-Lists-types ├── index.js ├── linked.js ├── readme.md └── test.js ├── 08-chapter-Hashing.js ├── 10-chapter-Binary-Tree ├── index.js ├── readme.md ├── test.js └── tree.module.js ├── 11-chapter-Graphs ├── graph.module.js ├── graph.search.js ├── readme.md └── test.js ├── 12-chapter-Sorting-Algorithms ├── basic-sort.js ├── index.js ├── merge-sort.module.js ├── quick-sort.module.js ├── readme.md ├── sort-module.js └── test.js ├── 13-chapter-Searching-Algorithms ├── index.js ├── paragraph.txt ├── readme.md ├── search-module.js └── test.js ├── README.md ├── index.js ├── package.json └── test.js /02-chapter-Array/02-chapter-Arrays.js: -------------------------------------------------------------------------------- 1 | class grades { 2 | 3 | constructor(grades = []) { 4 | this.grades = grades; 5 | } 6 | 7 | addGrade(grade) { 8 | this.grades = [...this.grades, grade]; 9 | } 10 | 11 | displayAvg(){ 12 | let sum = 0; 13 | this.grades.forEach(grade => sum += grade ); 14 | return sum / this.grades.length; 15 | } 16 | } 17 | 18 | // Implementation of the grade using classes 19 | console.log('### Excercise 1'); 20 | console.log('## Using ES6 Class, using the new keyword'); 21 | const gradeObj = [90,89,75,90,89,75,90,89,75,90,89,75,90,89,75,90,89,75]; 22 | const grade = new grades(gradeObj); 23 | grade.addGrade(90); 24 | grade.addGrade(25); 25 | console.log(`Avg grade: ${grade.displayAvg()}`); 26 | 27 | 28 | const gradesProto = { 29 | init(grades = []) { 30 | this.grades = grades; 31 | return this; 32 | }, 33 | addGrade(grade) { 34 | this.grades.push(grade); 35 | }, 36 | displayAvg() { 37 | let sum = this.grades.reduce((grades, grade) => grades += grade, 0); 38 | return sum / this.grades.length; 39 | } 40 | } 41 | 42 | // Implementation of the grade prototype 43 | console.log('\n## Using prototype, using Object.create()'); 44 | const gradeO = [90,89,75,90,89,75,90,89,75,90,89,75,90,89,75,90,89,75]; 45 | const gradeP = Object.create(gradesProto).init(gradeO); 46 | gradeP.addGrade(90); 47 | gradeP.addGrade(25); 48 | console.log(`Avg grade: ${gradeP.displayAvg()}`); 49 | 50 | const gradesFactory = () => { 51 | let grades = []; 52 | return { 53 | init(g = []) { 54 | grades = g; 55 | return this; 56 | }, 57 | addGrade(grade) { 58 | grades.push(grade); 59 | }, 60 | displayAvg() { 61 | let sum = grades.reduce((g, grade) => g += grade, 0); 62 | return sum / grades.length; 63 | } 64 | } 65 | } 66 | 67 | // Implementation of the grade factory 68 | console.log('\n## Using prototype, using factory'); 69 | const grade3 = gradesFactory().init(gradeO); 70 | grade3.addGrade(90); 71 | grade3.addGrade(25); 72 | console.log(`Avg grade: ${grade3.displayAvg()}`); 73 | 74 | // ############################################# 75 | console.log('\n### Excercise 2'); 76 | const arrayWords = ["hello ","my ","friend "]; 77 | console.log(`orginal array: ${arrayWords} `); 78 | console.log(`displaying forward: ${arrayWords.reduce((total, word) => total + word)}`); 79 | console.log(`displaying backward: ${arrayWords.reduceRight((total, word) => total + word)}`); 80 | 81 | // ############################################# 82 | class weekTemps { 83 | 84 | constructor(dataStore = []) { 85 | this.dataStore = dataStore; 86 | } 87 | 88 | add(temp) { 89 | this.dataStore = [...this.dataStore, temp]; 90 | } 91 | 92 | averageWeek(week) { 93 | let total = 0; 94 | let totalDays = this.dataStore[week].length; 95 | 96 | this.dataStore[week].forEach(item => total += item ); 97 | 98 | return (total / totalDays).toFixed(2); 99 | } 100 | 101 | displayMonthAvg() { 102 | let sum = 0; 103 | 104 | this.dataStore.forEach(week => 105 | week.forEach(day => sum += day ) 106 | ); 107 | 108 | return (sum / (this.dataStore.length * 4)).toFixed(2); 109 | } 110 | 111 | displayAllWeekAvg() { 112 | let sum = 0; 113 | 114 | this.dataStore.forEach((week, count) => { 115 | week.forEach(day => sum += day ); 116 | console.log(`Week ${count + 1} Temp Avg: ${(sum / week.length).toFixed(2)}`); 117 | sum = 0; 118 | }); 119 | 120 | } 121 | } 122 | 123 | // Implementation of weekTemps class 124 | console.log('\n### Excercise 3'); 125 | 126 | const randomMonth = [ 127 | [45,23,32,12,31,21,22], 128 | [12,12,13,11,9,34,23], 129 | [33,34,23,25,26,12,11], 130 | [14,15,18,19,22,24,25] 131 | ]; 132 | const thisMonth = new weekTemps(randomMonth); 133 | 134 | console.log(`Month Temp avg: ${thisMonth.displayMonthAvg()}`); 135 | console.log(`Week 2 Temp avg: ${thisMonth.averageWeek(2)}`); 136 | console.log(`\nDisplay All Week Avg`); 137 | thisMonth.displayAllWeekAvg(); 138 | 139 | 140 | const weekTempsProto = { 141 | init(dataStore = []) { 142 | this.dataStore = dataStore 143 | return this 144 | }, 145 | add(temp){ 146 | this.dataStore.push(temp) 147 | }, 148 | averageWeek(week) { 149 | let totalDays = this.dataStore[week].length 150 | let total = this.dataStore[week].reduce((week, day) => week += day, 0) 151 | return (total / totalDays).toFixed(2) 152 | }, 153 | displayMonthAvg() { 154 | let sum = this.dataStore.reduce((weeks, week) => 155 | weeks + week.reduce((days, day) => days + day, 0) 156 | , 0) 157 | return (sum / (this.dataStore.length * 4)).toFixed(2) 158 | }, 159 | displayAllWeekAvg() { 160 | let sum = 0 161 | this.dataStore.forEach((week, count) => { 162 | week.forEach(day => sum += day ) 163 | console.log(`Week ${count + 1} Temp Avg: ${(sum / week.length).toFixed(2)}`) 164 | sum = 0 165 | }); 166 | } 167 | }; 168 | 169 | // Implementation of weekTemps prototype object 170 | console.log('\n## Using prototype') 171 | 172 | const month = Object.create(weekTempsProto).init(randomMonth) 173 | 174 | console.log(`Month Temp avg: ${month.displayMonthAvg()}`) 175 | console.log(`Week 2 Temp avg: ${month.averageWeek(2)}`) 176 | console.log(`\nDisplay All Week Avg`) 177 | month.displayAllWeekAvg() 178 | 179 | console.log(JSON.stringify(weekTempsProto, null, 2)); 180 | 181 | // ############################################# 182 | console.log('\n### Excercise 4'); 183 | 184 | const letters = ['a','b','a','c','a','d','a','b','r','a']; 185 | console.log(letters.reduce((all, letter) => all + letter)); 186 | -------------------------------------------------------------------------------- /02-chapter-Array/readme.md: -------------------------------------------------------------------------------- 1 | # Array data structure 2 | 3 | ### Examples 4 | - [Array exercises and examples codes in ES6](./02-chapter-Arrays.js) 5 | 6 | ### Definition 7 | 8 | The array is the most common data structure in computer programming. Arrays are usually very efficient and are considered good choices for many data storage purposes. 9 | 10 | Arrays in JavaScript are very flexible. There are several different ways to create arrays, access array elements, and perform tasks such as searching and sorting the elements stored in an array. 11 | 12 | ``` 13 | const myArray = [1, 'one', {some: 'object'}, new Date()] 14 | ``` 15 | ![](https://docs.oracle.com/javase/tutorial/figures/java/objects-tenElementArray.gif) 16 | 17 | ### Usage of arrays 18 | 19 | **Creating an array** 20 | 21 | ``` 22 | /**** create new variable ****/ 23 | const grades = [1,2,3]; // this is the best way to create an array. 24 | const grades = new Array(1,2,3); // use of the constructor. 25 | const grades = new Array(3); // will initialize the array with the length of 3. 26 | const newGradesArray = [...grades, grade]; // will declare the newGradesArray variable and assign the values from the grades array and from grade. 27 | /**** create new variable ****/ 28 | 29 | /**** change const to let ****/ 30 | let grades = [1,2,3]; // this is the best way to create an array. 31 | let grades = new Array(1,2,3); // use of the constructor. 32 | let grades = new Array(3); // will initialize the array with the length of 3. 33 | grades = [...grades, grade]; // will reinstantiate the grades variable. 34 | /**** change const to let ****/ 35 | 36 | // use of the concat() function. 37 | const a = [1,2,3]; 38 | const b = [4,5,6]; 39 | const c = a.concat(b); // this creates a new array by concatenating the 2 arrays. 40 | 41 | ``` 42 | or using strings to create an array, by using the ***split*** method and space ' ' delimiter will create a new array containg the words of the text. 43 | ``` 44 | const words = someStringText.split(' '); 45 | ``` 46 | 47 | **Inserting elements to an array** 48 | 49 | There are several ways to add a new element to the array for example: 50 | 51 | ``` 52 | // This two operations will add a new element at the end of the array. 53 | grades.push(element); 54 | grades[grades.length + 1] = grade; 55 | 56 | // use of unshift() method will insert a new element at the front of the array. 57 | grades.unshift(grade); 58 | 59 | //use of the splice() method will insert a new element at the position indicated. 60 | grades.splice(position, 0, grade); 61 | ``` 62 | The splice() method, has the ability to insert or to remove an element, the first parameter of the method indicates the position, the second parameter indicates the type of operation 0 = insert, 1 = delete, and the third parameter is the new value to insert. 63 | 64 | **Deleting elements to an array** 65 | 66 | ``` 67 | // use of the splice() method. 68 | grades.splice(position, numElementsToDelete); 69 | ``` 70 | -------------------------------------------------------------------------------- /03-chapter-List.js: -------------------------------------------------------------------------------- 1 | class List { 2 | constructor(dataStore = [], listSize = 0, pos = 0) { 3 | this.dataStore = dataStore; 4 | this.listSize = listSize; 5 | this.pos = pos; 6 | } 7 | 8 | clear() { 9 | this.dataStore = []; 10 | this.pos = 0; 11 | this.listSize = 0; 12 | } 13 | 14 | find(element) { 15 | return this.dataStore.findIndex(e => e === element); 16 | } 17 | 18 | insert(element, after) { 19 | const insertPos = this.find(after); 20 | if (insertPos != -1 ) { 21 | this.dataStore.splice(insertPos+1, 0, element); 22 | this.listSize++; 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | append(element) { 29 | this.dataStore = [...this.dataStore, element]; 30 | this.listSize++; 31 | } 32 | 33 | remove(element) { 34 | const removePos = this.find(element); 35 | if(removePos != -1) { 36 | this.dataStore.splice(removePos, 1); 37 | this.listSize--; 38 | return true; 39 | } 40 | return false; 41 | } 42 | 43 | front() { 44 | this.pos = 0; 45 | } 46 | 47 | end() { 48 | this.pos = this.listSize - 1; 49 | } 50 | 51 | prev() { 52 | if (this.pos > 0) { 53 | --this.pos; 54 | } 55 | } 56 | 57 | next() { 58 | if (this.pos < this.listSize - 1) { 59 | ++this.pos; 60 | } 61 | } 62 | 63 | length() { 64 | return this.listSize; 65 | } 66 | 67 | currPos() { 68 | return this.pos; 69 | } 70 | 71 | moveTo(position) { 72 | this.pos = position 73 | } 74 | 75 | getElement() { 76 | return this.dataStore[this.pos]; 77 | } 78 | 79 | contains(element) { 80 | return (this.dataStore.find(value => value === element) != undefined ) ? true : false; 81 | } 82 | 83 | displayList() { 84 | this.dataStore.forEach((item, counter) => { 85 | console.log(`${counter + 1}.- ${item}`); 86 | }) 87 | } 88 | 89 | toString() { 90 | return JSON.stringify(this.dataStore); 91 | } 92 | } 93 | 94 | // Class GenericList for Excercise 1 and 2 95 | // ################################### 96 | class GenericList extends List { 97 | constructor(dataStore, listSize) { 98 | super(dataStore, listSize); 99 | } 100 | 101 | insertGraterThan(element) { 102 | let grater = false; 103 | let value = 0; 104 | for (const key in this.dataStore) { 105 | if( typeof element !== 'string' && typeof this.dataStore[key] === 'string' || 106 | typeof element === 'string' && typeof this.dataStore[key] !== 'string' ) { 107 | continue; 108 | } 109 | value = (typeof element === 'string') ? this.dataStore[key] + '' : this.dataStore[key]; 110 | grater = (element > value) ? true : false; 111 | } 112 | if(grater) { 113 | this.dataStore.push(element); 114 | console.log(`The element: ${element} is grater than elemnt's in the list`); 115 | } else { 116 | console.log(`The element: ${element} is not grater than elemnt's in the list`); 117 | } 118 | } 119 | 120 | insertSmallerThan(element) { 121 | let smaller = false; 122 | let value = 0; 123 | for (const key in this.dataStore) { 124 | if( typeof element !== 'string' && typeof this.dataStore[key] === 'string' || 125 | typeof element === 'string' && typeof this.dataStore[key] !== 'string' ) { 126 | continue; 127 | } 128 | value = (typeof element === 'string') ? this.dataStore[key] + '' : this.dataStore[key]; 129 | smaller = (element < value) ? true : false; 130 | } 131 | if(smaller) { 132 | this.dataStore.push(element); 133 | console.log(`The element: ${element} is smaller than elemnt's in the list`); 134 | } else { 135 | console.log(`The element: ${element} is not smaller than elemnt's in the list`); 136 | } 137 | } 138 | } 139 | 140 | 141 | // Implementations 142 | // ################################### 143 | /* 144 | 1.- Write a function that inserts an element into a list only if the element to be inserted 145 | is larger than any of the elements currently in the list. Larger can mean either greater 146 | than when working with numeric values, or further down in the alphabet, when working with textual values. 147 | */ 148 | console.log('CHAPTER 3'); 149 | console.log('### Excercise 1'); 150 | 151 | // Numeric list only 152 | const list = new GenericList([1,4,5,7], 4); 153 | list.insertGraterThan(6); 154 | list.insertGraterThan(15); 155 | console.log(list.toString()); 156 | 157 | // string list only 158 | const list2 = new GenericList(['a','c','f','g'], 4); 159 | list2.insertGraterThan('b'); 160 | list2.insertGraterThan('z'); 161 | console.log(list2.toString()); 162 | 163 | // mixed list 164 | const list3 = new GenericList([1,'c',2,'g'], 4); 165 | list3.insertGraterThan('b'); 166 | list3.insertGraterThan('z'); 167 | list3.insertGraterThan(3); 168 | list3.insertGraterThan(0); 169 | console.log(list3.toString()); 170 | 171 | // ################################### 172 | /* 173 | 2.- Write a function that inserts an element into a list only if the element to be inserted 174 | is smaller than any of the elements currently in the list. 175 | */ 176 | console.log('\n\n### Excercise 2'); 177 | 178 | // Numeric list only 179 | const list4 = new GenericList([1,4,5,7], 4); 180 | list4.insertSmallerThan(2); 181 | list4.insertSmallerThan(15); 182 | console.log(list4.toString()); 183 | 184 | // string list only 185 | const list5 = new GenericList(['a','c','f','g'], 4); 186 | list5.insertSmallerThan('b'); 187 | list5.insertSmallerThan('z'); 188 | console.log(list5.toString()); 189 | 190 | // mixed list 191 | const list6 = new GenericList([1,'c',2,'g'], 4); 192 | list6.insertSmallerThan('b'); 193 | list6.insertSmallerThan('z'); 194 | list6.insertSmallerThan(3); 195 | list6.insertSmallerThan(0); 196 | console.log(list6.toString()); 197 | 198 | // Class People for Excercise 3 199 | // ################################### 200 | class People { 201 | constructor(name = 'generic Doe', gender = 'generic') { 202 | this.name = name; 203 | this.gender = gender; 204 | } 205 | } 206 | 207 | class PeopleList extends List { 208 | 209 | displayByGender(gender) { 210 | console.log(`Displaying only people who has the gender: ${gender}`); 211 | this.dataStore.forEach((person, counter) => { 212 | if(person.gender === gender){ 213 | console.log(`${counter + 1}.- ${person.name}`); 214 | } 215 | }); 216 | } 217 | } 218 | 219 | /* 220 | 3.- Create a Person class that stores a person’s name and their gender. 221 | Create a list of at least 10 Person objects. Write a function that displays 222 | all the people in the list of the same gender. 223 | */ 224 | console.log('\n\n### Excercise 3'); 225 | 226 | const p1 = new People('Jhon Doe', 'male'); 227 | const p2 = new People('Jane Doe', 'female'); 228 | const p3 = new People('Jose Doe', 'male'); 229 | const p4 = new People('Lady Doe', 'female'); 230 | const p5 = new People('Juan Colorado', 'male'); 231 | const p6 = new People('Maritza Doe', 'female'); 232 | const p7 = new People('Cris Ramirez', 'male'); 233 | const p8 = new People('More Ramirez', 'female'); 234 | const p9 = new People('Lenin Ramirez', 'male'); 235 | const p10 = new People('Jessy Doe', 'female'); 236 | 237 | const peopleList = new PeopleList(); 238 | peopleList.append(p1); 239 | peopleList.append(p2); 240 | peopleList.append(p3); 241 | peopleList.append(p4); 242 | peopleList.append(p5); 243 | peopleList.append(p6); 244 | peopleList.append(p7); 245 | peopleList.append(p8); 246 | peopleList.append(p9); 247 | peopleList.insert(p10,p3.name); 248 | peopleList.displayByGender('male'); 249 | peopleList.displayByGender('female'); 250 | 251 | 252 | // Class People for Excercise 4 253 | // ################################### 254 | 255 | class Customer { 256 | constructor(name = 'Juan Colorado', movie = 'Monarcas Morelia Movie') { 257 | this.name = name; 258 | this.movie = movie; 259 | } 260 | } 261 | 262 | class MovieStore extends List { 263 | 264 | constructor(rentedList = new List()) { 265 | super(); 266 | this.rentedList = rentedList; 267 | } 268 | 269 | checkOut(name, movie, customerList) { 270 | if(this.contains(movie)) { 271 | const c = new Customer(name, movie); 272 | customerList.append(c); 273 | this.remove(movie); 274 | this.rentedList.append(movie); 275 | console.log('\nMovies rented: '); 276 | this.rentedList.displayList(); 277 | } else { 278 | console.log(`\n${movie} is not available to rent or is already rented`); 279 | } 280 | } 281 | 282 | checkIn(movie, customer, customerList) { 283 | if(this.rentedList.contains(movie)) { 284 | this.rentedList.remove(movie); 285 | this.append(movie); 286 | // customerList.remove(customer.name); 287 | } 288 | } 289 | 290 | } 291 | 292 | /* 293 | 4.- Modify the video-rental kiosk program so that when a movie is checked out it 294 | is added to a list of rented movies. Display this list whenever a customer 295 | checks out a movie. 296 | */ 297 | console.log('\n\n### Excercise 4'); 298 | const readline = require('readline'); 299 | const fs = require('fs'); 300 | 301 | const movieStore = new MovieStore(); 302 | 303 | const rl = readline.createInterface({ 304 | input: fs.createReadStream('movies.txt') 305 | }); 306 | 307 | rl.on('line', (line) => movieStore.append(line)); 308 | 309 | rl.on('close', () => { 310 | const customers = new List(); 311 | console.log('\nAvailable movies:'); 312 | movieStore.displayList(); 313 | movieStore.checkOut("Jane Doe", "The Godfather", customers); 314 | movieStore.checkOut("Jhon Doe", "Fight Club", customers); 315 | movieStore.checkOut("Cris Ramirez", "Inception", customers); 316 | movieStore.checkOut("Maritza Doe", "The Godfather", customers); 317 | console.log('\nCustomer Rentals:'); 318 | console.log(customers.toString(), '\n'); 319 | 320 | // ################################### 321 | /* 322 | 5.- Create a check-in function for the video-rental kiosk program so that a 323 | returned movies is deleted from the rented movies list and is added back 324 | to the available movies list. 325 | */ 326 | console.log('\n\n### Excercise 5'); 327 | movieStore.checkIn('Inception', 'Cris Ramirez', customers); 328 | movieStore.checkIn('The Godfather', 'Jane Doe', customers); 329 | console.log('\nAvailable movies:'); 330 | movieStore.displayList(); 331 | console.log('\nMovies rented: '); 332 | movieStore.rentedList.displayList(); 333 | }); 334 | -------------------------------------------------------------------------------- /04-chapter-Stack/index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {stack} = require('./stack.module') 3 | Object.assign(exports, {stack}) 4 | }((typeof module.exports !== undefined) ? module.exports : window)) 5 | -------------------------------------------------------------------------------- /04-chapter-Stack/readme.md: -------------------------------------------------------------------------------- 1 | # Stacks with ES6 2 | 3 | ### Code Examples 4 | - [Stack Data Structure](./stack.module.js) 5 | - [Import Module](./index.js) 6 | 7 | ### Description 8 | 9 | Pattern type: Last item In is the First item Out (LIFO) 10 | 11 | ![](https://cdn-images-1.medium.com/max/800/0*S3Kr9Cpm16ZmCEad.png) 12 | 13 | common operations you can perform on graphs: 14 | - `push`: adds a new element to the stack 15 | - `pop`: remove the last item pushed from the stack 16 | - `peek`: returns the last item pushed to stack 17 | - `length`: returns the size of the stack 18 | - `isEmpty`: returns true if the stack has elements or false if it has no elements 19 | - `getStack`: returns the data of the stack 20 | 21 | ### Example use case 22 | - Using the back and forward buttons in your browser 23 | - dfs search algorithm for graphs search 24 | - balanced arithmetic operations 25 | - convert infix to postfix arithmetic operations 26 | - JS engine uses a stack data structure to execute the algorithms 27 | 28 | 29 | ### Resources 30 | 31 | - [A Gentle Introduction to Data Structures: How Stacks Work](https://medium.freecodecamp.com/data-structures-stacks-on-stacks-c25f2633c529#.3omw867a9) 32 | -------------------------------------------------------------------------------- /04-chapter-Stack/stack.module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const stack = (data = [], t = 0) => { 3 | let dataStore = data 4 | let top = t 5 | 6 | const stackProto = { 7 | push (element) { 8 | dataStore[top++] = element 9 | }, 10 | pop: () => dataStore.splice(--top, 1), 11 | peek: () => dataStore[top - 1], 12 | length: () => top, 13 | isEmpty: () => top === 0, 14 | getStack: () => dataStore 15 | } 16 | 17 | return Object.create(stackProto) 18 | } 19 | 20 | Object.assign(exports, {stack}) 21 | }((typeof module.exports !== undefined) ? module.exports : window)) 22 | -------------------------------------------------------------------------------- /04-chapter-Stack/test.js: -------------------------------------------------------------------------------- 1 | const {stack} = require('./index') 2 | 3 | function checkBalancedExpression (e) { 4 | const s = stack() 5 | let balanced = true 6 | 7 | for (const key in e) { 8 | if (e[key] === '(') { 9 | s.push(e[key]) 10 | } else if (e[key] === ')') { 11 | if (s.length() === 0) { 12 | balanced = false 13 | } 14 | s.pop() 15 | } 16 | } 17 | if (s.length() > 0) { 18 | balanced = false 19 | } 20 | return balanced 21 | } 22 | 23 | function checkOperator (op) { 24 | switch (op) { 25 | case ')': 26 | return 4 27 | case '(': 28 | return 3 29 | case '/': 30 | return 2 31 | case '*': 32 | return 2 33 | case '+': 34 | return 1 35 | case '-': 36 | return 1 37 | } 38 | } 39 | 40 | function infixToPostfix(exp) { 41 | let value = '' 42 | const s = stack() 43 | const postfix = stack() 44 | 45 | for (const key in exp) { 46 | if (exp[key] === '(' || exp[key] === ')' || exp[key] === '+' || 47 | exp[key] === '-' || exp[key] === '*' || exp[key] === '/' ) { 48 | if (value !== '') { 49 | postfix.push(value) 50 | } 51 | if (s.length() === 0 && exp[key] !== '(') { 52 | s.push(exp[key]) 53 | } else { 54 | if (checkOperator(exp[key]) !== 3) { 55 | innerLoop: 56 | while (s.length() > 0) { 57 | if (checkOperator(exp[key]) < checkOperator(s.peek())) { 58 | postfix.push(s.peek()) 59 | s.pop() 60 | } else if (checkOperator(exp[key]) === checkOperator(s.peek())) { 61 | postfix.push(s.peek()) 62 | s.pop() 63 | s.push(exp[key]) 64 | break innerLoop 65 | } else { 66 | if (checkOperator(exp[key]) !== 4) { 67 | s.push(exp[key]) 68 | } 69 | break innerLoop 70 | } 71 | } 72 | } 73 | } 74 | value = '' 75 | } else { 76 | value += exp[key] 77 | } 78 | } 79 | 80 | while (s.length() > 0) { 81 | postfix.push(s.peek()) 82 | s.pop() 83 | } 84 | return postfix 85 | } 86 | 87 | function evalPostFix (exp) { 88 | const resultStack = stack() 89 | const postfix = exp.getStack() 90 | 91 | for (const key in postfix) { 92 | if (!isNaN(postfix[key])) { 93 | resultStack.push(postfix[key]) 94 | } else { 95 | const a = resultStack.peek() 96 | resultStack.pop() 97 | const b = resultStack.peek() 98 | resultStack.pop() 99 | 100 | if (postfix[key] === '+') { 101 | resultStack.push((parseFloat(a, 10) + parseFloat(b, 10)).toFixed(2)) 102 | } else if (postfix[key] === '-') { 103 | resultStack.push((parseFloat(b, 10) - parseFloat(a, 10)).toFixed(2)) 104 | } else if (postfix[key] === '*') { 105 | resultStack.push((parseFloat(a, 10) * parseFloat(b, 10)).toFixed(2)) 106 | } else if (postfix[key] === '/') { 107 | resultStack.push((parseFloat(b, 10) / parseFloat(a, 10)).toFixed(2)) 108 | } 109 | } 110 | } 111 | return resultStack.getStack() 112 | } 113 | 114 | test('Stack ES6 module', assert => { 115 | let exp = '2.3 + 23 / 12 + (3.14159 * .24' 116 | let e = exp.split('') 117 | 118 | e = e.filter(item => item !== ' ') 119 | let balanced = checkBalancedExpression(e) 120 | 121 | let exp2 = '2.3 + (23 / 12) + (3.14159 * .24)' 122 | let e2 = exp2.split('') 123 | 124 | e2 = e2.filter(item => item !== ' ') 125 | let balanced2 = checkBalancedExpression(e2) 126 | 127 | assert.equal(false, balanced, `The expression '${exp}' is no balanced`) 128 | 129 | assert.equal(true, balanced2, `The expression '${exp2}' is balanced`) 130 | 131 | const postfix = infixToPostfix(e2) 132 | let result = postfix.getStack().reduce((total, value) => total + ' ' + value ) 133 | 134 | assert.equal(result, '2.3 23 12 / + 3.14159 .24 * +', 'convert Infix To Postfix') 135 | 136 | result = evalPostFix(postfix) 137 | 138 | assert.equal(result, '4.97', 'evaluation of postfix') 139 | }) 140 | -------------------------------------------------------------------------------- /05-chapter-Queue/index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {queue} = require('./queue.module') 3 | Object.assign(exports, {queue}) 4 | }((typeof module.exports !== undefined) ? module.exports : window)) 5 | -------------------------------------------------------------------------------- /05-chapter-Queue/queue.module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const queue = (data = []) => { 3 | let dataStore = data 4 | 5 | const queueProto = { 6 | enqueue: (element) => dataStore.push(element), 7 | dequeue: () => dataStore.shift(), 8 | front: () => dataStore[0], 9 | back: () => dataStore[dataStore.length - 1], 10 | isEmpty: () => dataStore.length === 0, 11 | length: () => dataStore.length, 12 | getQueue: () => dataStore, 13 | setQueue: (data) => { 14 | dataStore = data 15 | }, 16 | toString: () => JSON.stringify(dataStore, null, 2) 17 | } 18 | 19 | return Object.create(queueProto) 20 | } 21 | 22 | Object.assign(exports, {queue}) 23 | }((typeof module.exports !== undefined) ? module.exports : window)) 24 | -------------------------------------------------------------------------------- /05-chapter-Queue/readme.md: -------------------------------------------------------------------------------- 1 | # Queue with ES6 2 | 3 | ### Code Examples 4 | - [Queue Data Structure](./queue.module.js) 5 | - [Import Module](./index.js) 6 | 7 | ### Description 8 | A queue is a type of list where data are inserted at the end and are removed from the front. Queues are used to store data in the order in which they occur, as opposed to a stack, in which the last piece of data entered is the first element used for processing. Think of a queue like the line at your bank, where the first person into the line is the first person served, and as more customers enter a line, they wait in the back until it is their turn to be served. 9 | 10 | A queue is an example of a first-in, first-out (FIFO) data structure. Queues are used to order processes submitted to an operating system or a print spooler, and simulation applications use queues to model scenarios such as customers standing in the line at a bank or a grocery store. 11 | 12 | ![](https://cdn-images-1.medium.com/max/800/0*SFoM_gyGXk8MIfl4.png) 13 | 14 | common operations you can perform on graphs: 15 | - `enqueue`: adds a new element to the queue at the last position 16 | - `dequeue`: remove the first item from the queue 17 | - `front`: returns the first item pushed to queue 18 | - `back`: returns the last item pushed to queue 19 | - `length`: returns the size of the queue 20 | - `isEmpty`: returns true if the queue has elements or false if it has no elements 21 | - `getQueue`: returns the data of the queue 22 | 23 | ### Example use cases 24 | - Resolving simultaneous server requests from multiple users, such as 3 people buying the last ticket for a plane at almost the same time 25 | - Queuing up data during a breadth-first search. 26 | -------------------------------------------------------------------------------- /05-chapter-Queue/test.js: -------------------------------------------------------------------------------- 1 | const {queue} = require('./index') 2 | 3 | test('Queue test 1', assert => { 4 | const patient = (name = 'generic', code = '0') => Object.assign({}, {name, code}) 5 | 6 | const ed = queue() 7 | const p = patient('Smith', 5) 8 | ed.enqueue(p) 9 | const p2 = patient('Jones', 4) 10 | ed.enqueue(p2) 11 | const p3 = patient('Fehrenbach', 6) 12 | ed.enqueue(p3) 13 | const p4 = patient('Brown', 1) 14 | ed.enqueue(p4) 15 | const p5 = patient('Ingram', 1) 16 | ed.enqueue(p5) 17 | 18 | const dequeue = function () { 19 | let priority = this.front().code 20 | let position = 0 21 | let dataStore = this.getQueue() 22 | for (let i = 0; i < this.length(); i++) { 23 | if (dataStore[i].code >= priority) { 24 | priority = dataStore[i].code 25 | position = i 26 | } 27 | } 28 | return dataStore.splice(position, 1) 29 | } 30 | 31 | Object.assign(ed, {dequeue}) 32 | 33 | let seen = [] 34 | 35 | while (ed.length() > 0) { 36 | let {name} = ed.dequeue()[0] 37 | seen.push(name) 38 | // console.log('\nPatient being treated: ' + seen[seen.length - 1]) 39 | } 40 | 41 | assert.equal(seen[0], 'Fehrenbach', 'dequeue fn override and dequeue by code') 42 | }) 43 | 44 | test('Queue test 2', assert => { 45 | function isPalindrome (word) { 46 | const letter = new RegExp('[a-z]') 47 | let palindrome = word.toLowerCase().split('') 48 | let a, b 49 | palindrome = palindrome.filter(item => letter.test(item)) 50 | const q = queue(palindrome) 51 | 52 | const dequeueBack = function (element) { 53 | const dataStore = this.getQueue() 54 | const data = dataStore.unshift(element) 55 | this.setQueue(data) 56 | return data 57 | } 58 | 59 | Object.assign(q, {dequeueBack}) 60 | 61 | while (!q.isEmpty()) { 62 | if (q.length() > 1) { 63 | a = q.front() 64 | b = q.back() 65 | } else { 66 | // console.log(`The string '${word.toUpperCase()}' is palindrome!`) 67 | return true 68 | } 69 | if (a === b && q.length() > 1) { 70 | q.dequeue() 71 | q.dequeueBack() 72 | } else { 73 | // console.log(`The string '${word.toUpperCase()}' is not palindrome!`) 74 | return false 75 | } 76 | } 77 | } 78 | 79 | const word = 'racecar' 80 | const word2 = 'A man, a plan, a canal: Panama' 81 | const word3 = 'what is this' 82 | 83 | assert.equal(true, isPalindrome(word), `the string = '${word}' is palindrome`) 84 | assert.equal(true, isPalindrome(word2), `the string = '${word2}' is palindrome`) 85 | assert.equal(false, isPalindrome(word3), `the string = '${word3}' is not a palindrome`) 86 | }) 87 | -------------------------------------------------------------------------------- /06-chapter-Linked-Lists-types/index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const linked = require('./linked') 3 | Object.assign(exports, linked) 4 | }((typeof module.exports !== 'undefined') ? module.exports : window)) 5 | -------------------------------------------------------------------------------- /06-chapter-Linked-Lists-types/linked.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | // helper functions 3 | const compose = (...fns) => data => fns.reduce((v, f) => f(v), data) 4 | 5 | // makes Concatenative Inheritance 6 | const inherit = (...protos) => Object.assign({}, ...protos) 7 | 8 | /** 9 | base prototype for all linked list types 10 | 11 | all functions are pure functions, since they don't realy on external state 12 | and produces no side effects, since they are not mutating external objects 13 | **/ 14 | const base = { 15 | node (data, ...rest) { 16 | const prev = (rest[0] === 'double') ? {prev: null} : {} 17 | return Object.assign({}, {data, next: null}, prev) 18 | }, 19 | setHead (options) { 20 | let {head, data} = options 21 | Object.assign(options, {head: data}) 22 | return options 23 | }, 24 | setCurrent (options) { 25 | let {current, data} = options 26 | Object.assign(options, {current: data}) 27 | return options 28 | }, 29 | setLength (options) { 30 | let {length, data} = options 31 | length += ((data) ? 1 : -1) 32 | Object.assign(options, {length}) 33 | return options 34 | }, 35 | setNext (options) { 36 | let {data} = options 37 | Object.assign(options.current, {next: data}) 38 | return options 39 | }, 40 | findPrev (options) { 41 | let {head, data} = options 42 | let c = head 43 | while (!(c.next === null)) { 44 | if (c.next.data === data) { 45 | return c 46 | } else { 47 | c = c.next 48 | } 49 | } 50 | return false 51 | } 52 | } 53 | 54 | // single-linked list prototype 55 | const single = { 56 | getState () { 57 | return this 58 | }, 59 | setState (options) { 60 | Object.assign(this, options) 61 | }, 62 | add (data) { 63 | // retrieves the variables and concatenate the new node to be added 64 | const options = Object.assign(this.getState(), {data: this.node(data)}) 65 | const fns = (!this.head && !this.current) ? [this.setHead] : [this.setNext] 66 | // and through function composition, adds an element to the list 67 | // and the result object it's going to be re assign it to the current state 68 | compose(...fns, this.setCurrent, this.setLength, this.setState)(options) 69 | }, 70 | remove (data) { 71 | // retrieves variables 72 | const options = Object.assign(this.getState(), {data}) 73 | // look if there's a previous link 74 | const prev = this.findPrev(options) 75 | let values, fns 76 | if (prev && !(prev.next === null)) { 77 | // updates the corresponding values to remove the requested object 78 | values = {current: prev, data: prev.next.next} 79 | // functions need to compose to remove the object requested 80 | fns = [this.setNext, this.setState] 81 | } else { 82 | values = {data: options.head.next} 83 | fns = [this.setHead, this.setState] 84 | } 85 | compose(...fns)(Object.assign(options, values)) // removes the object 86 | this.setLength(Object.assign(options, {data: false})) // decreases the length 87 | }, 88 | reverse() { 89 | let prev = null 90 | let node = this.head 91 | 92 | while (node) { 93 | let save = node.next 94 | node.next = prev 95 | prev = node 96 | node = save 97 | } 98 | Object.assign(this.getState(), {head: prev}) 99 | }, 100 | display () { 101 | let c = this.head 102 | let show = '' 103 | while (!(c === null)) { 104 | show += `${c.data} ${(c.next !== null) ? ' -> ' : ''}` 105 | c = c.next 106 | } 107 | return show 108 | }, 109 | contains (data) { 110 | let c = this.head 111 | while (!(c === null)) { 112 | if (c.data === data) { 113 | return true 114 | } 115 | c = c.next 116 | } 117 | return false 118 | }, // the next functions returns a copy of the object requested 119 | getCurrent() { 120 | return Object.assign({}, this.current) 121 | }, 122 | getList() { 123 | return Object.assign({}, this.head) 124 | }, 125 | size() { 126 | return this.length 127 | } 128 | } 129 | 130 | // double-linked list prototype 131 | const double = { 132 | add (data) { 133 | const options = Object.assign(this.getState(), {data: this.node(data, 'double')}) 134 | const fns = (!this.head && !this.current) ? [this.setHead] : [this.setNext, this.setPrev] 135 | compose(...fns, this.setCurrent, this.setLength, this.setState)(options) 136 | }, 137 | remove (data) { 138 | const options = Object.assign(this.getState(), {data}) 139 | let prev = this.findPrev(options) 140 | let values, fns 141 | if (prev && !(prev.next === null)) { 142 | values = {current: prev, data: prev.next.next} 143 | fns = [this.setPrev, this.setNext, this.setState] 144 | } else { 145 | values = { 146 | data: { 147 | data: options.head.next.data, 148 | next: options.head.next.next, 149 | prev: null 150 | } 151 | } 152 | fns = [this.setHead, this.setState] 153 | } 154 | compose(...fns)(Object.assign(options, values)) 155 | this.setLength(Object.assign(options, {data: false})) 156 | } 157 | } 158 | 159 | // circular-linked list prototype 160 | const circular = { 161 | display () { 162 | let c = this.head 163 | let show = `${c.data} ${(c.next !== this.head) ? ' -> ' : ''}` 164 | while (!(c.next === this.head)) { 165 | show += `${c.next.data} ${(c.next !== this.head) ? ' -> ' : ''}` 166 | c = c.next 167 | } 168 | return show 169 | }, 170 | contains(data) { 171 | let c = this.head 172 | while (!(c.next === this.head)) { 173 | if (c.data === data) { 174 | return true 175 | } 176 | c = c.next 177 | } 178 | return false 179 | } 180 | } 181 | 182 | const singleLL = () => { 183 | const variables = { head: null, current: null, length: 0 } 184 | const proto = inherit(base, single) 185 | return Object.assign(Object.create(proto), variables) 186 | } 187 | 188 | const doubleLL = () => { 189 | // fn to set the prev link object in the double-linked list 190 | const setPrev = (options) => { 191 | let {current, data} = options 192 | if (data !== null) { 193 | Object.assign(options.data, {prev: current}) 194 | } 195 | return options 196 | } 197 | 198 | const variables = { head: null, current: null, length: 0 } 199 | // first is updated the base prototype 200 | const b = Object.assign(base, {setPrev}) 201 | /* 202 | then we make an Concatenative Inheritance 203 | with the base prototype that give us the basic operations, 204 | with the single prototype that gives the linked lists interface 205 | and finally set the double prototype that overrides the needed methods 206 | */ 207 | const proto = inherit(b, single, double) 208 | /* 209 | and finally return the created prototype with its variables 210 | creating the variables in each type of linked list 211 | avoids the shared state on the prototype 212 | */ 213 | return Object.assign(Object.create(proto), variables) 214 | } 215 | 216 | const circularLL = () => { 217 | const setHead = (options) => { 218 | let {data} = options 219 | Object.assign(options, {head: data}) 220 | Object.assign(options.head, {next: options.head}) 221 | return options 222 | } 223 | const setNext = (options) => { 224 | let {data} = options 225 | let next 226 | if(data.next === null) { 227 | Object.assign(data, {next: options.head}) 228 | } 229 | Object.assign(options.current, {next: data}) 230 | return options 231 | } 232 | const setPrev = (options) => { 233 | let {data} = options 234 | let next 235 | if(data === null) { 236 | Object.assign(data, {data: options.head}) 237 | } else { 238 | Object.assign(data, {prev: options.current}) 239 | } 240 | return options 241 | } 242 | 243 | const variables = {head: null, current: null, length: 0} 244 | const b = Object.assign(base, {setHead, setNext, setPrev}) 245 | const proto = inherit(b, single, double, circular) 246 | 247 | return Object.assign(Object.create(proto), variables) 248 | } 249 | 250 | Object.assign(exports, {singleLL, doubleLL, circularLL}) 251 | 252 | }((typeof module.exports !== undefined) ? module.exports : window)) 253 | -------------------------------------------------------------------------------- /06-chapter-Linked-Lists-types/readme.md: -------------------------------------------------------------------------------- 1 | # Linked List, Double Linked List, Circular Linked List 2 | 3 | ### Code Examples 4 | 5 | - [Single, Double, Circular, Linked List, Data Structure](./linked.js) 6 | - [Import complete module](./index.js) 7 | 8 | ### Definition Linked List 9 | 10 | The simplest form of linked lists — a singly linked list — is a series of nodes where each individual node contains both a value and a pointer to the next node in the list. 11 | 12 | common operations you can perform on linked list: 13 | 14 | **Additions** 15 | - `add`: grow the list by adding items to the end of the list. 16 | **Removals** 17 | - `remove`: will always remove from a given position in the list. 18 | **Search** 19 | - `contains`: will search the list for a value. 20 | 21 | ### Definition Double Linked List 22 | 23 | Doubly Linked List is a variation of Linked list in which navigation is possible in both ways, either forward and backward easily as compared to Single Linked List. Following are the important terms to understand the concept of doubly linked list. 24 | 25 | - Link − Each link of a linked list can store a data called an element. 26 | 27 | - Next − Each link of a linked list contains a link to the next link called Next. 28 | 29 | - Prev − Each link of a linked list contains a link to the previous link called Prev. 30 | 31 | LinkedList − A Linked List contains the connection link to the first link called First and to the last link called Last. 32 | 33 | common operations you can perform on linked list: 34 | 35 | **Additions** 36 | - `add`: grow the list by adding items to the end of the list. 37 | **Removals** 38 | - `remove`: will always remove from a given position in the list. 39 | **Search** 40 | - `contains`: will search the list for a value. 41 | **Display** 42 | - `display`: displays the complete list in a forward manner. 43 | 44 | ### Definition Circular Linked List 45 | 46 | Circular Linked List is a variation of Linked list in which the first element points to the last element and the last element points to the first element. Both Singly Linked List and Doubly Linked List can be made into a circular linked list. 47 | 48 | Singly Linked List as Circular 49 | 50 | In singly linked list, the next pointer of the last node points to the first node 51 | 52 | Doubly Linked List as Circular 53 | 54 | In doubly linked list, the next pointer of the last node points to the first node and the previous pointer of the first node points to the last node making the circular in both directions. 55 | 56 | common operations you can perform on linked list: 57 | 58 | **Additions** 59 | - `add`: grow the list by adding items to the end of the list. 60 | **Removals** 61 | - `remove`: will always remove from a given position in the list. 62 | **Search** 63 | - `contains`: will search the list for a value. 64 | **Display** 65 | - `display`: displays the complete list in a forward manner. 66 | 67 | ### Example use cases 68 | - Storing values in a hash table to prevent collisions 69 | 70 | ### Resources 71 | 72 | - [Data Structure and Algorithms - Linked List](https://www.tutorialspoint.com/data_structures_algorithms/linked_list_algorithms.htm) 73 | -------------------------------------------------------------------------------- /06-chapter-Linked-Lists-types/test.js: -------------------------------------------------------------------------------- 1 | const {singleLL, doubleLL, circularLL} = require('./index') 2 | 3 | test('Linked List test', assert => { 4 | const amazingRace = singleLL() 5 | 6 | amazingRace.add('Colombo, Sri Lanka') 7 | amazingRace.add('Lagos, Nigeria') 8 | amazingRace.add('Surat, India') 9 | amazingRace.add('Suzhou, China') 10 | 11 | assert.equal(4, amazingRace.size(), 'can get the size of the linked list') 12 | amazingRace.add('Hanoi, Vietnam') 13 | amazingRace.add('Seattle, Washington') 14 | amazingRace.add('North Pole') 15 | 16 | amazingRace.remove('North Pole') 17 | amazingRace.remove('Hanoi, Vietnam') 18 | 19 | console.log(amazingRace.display()) 20 | console.log(amazingRace.size()) 21 | 22 | assert.equal(amazingRace.size(), 5, 'can remove elements') 23 | 24 | amazingRace.reverse() 25 | console.log(amazingRace.display()) 26 | console.log(amazingRace.size()) 27 | 28 | amazingRace.reverse() 29 | console.log(amazingRace.display()) 30 | 31 | }) 32 | -------------------------------------------------------------------------------- /08-chapter-Hashing.js: -------------------------------------------------------------------------------- 1 | // HashTable data structure class example 2 | class HashTable { 3 | constructor() { 4 | this.table = new Array(137); 5 | this.values = []; 6 | } 7 | 8 | hash(string) { 9 | const H = 37; 10 | let total = 0; 11 | 12 | for (var i = 0; i < string.length; i++) { 13 | total += H * total + string.charCodeAt(i); 14 | } 15 | total %= this.table.length; 16 | if (total < 1) { 17 | this.table.length -1 18 | } 19 | return parseInt(total); 20 | } 21 | 22 | showDistro() { 23 | for (const key in this.table) { 24 | if(this.table[key] !== undefined) { 25 | console.log(key, ' : ', this.table[key]); 26 | } 27 | } 28 | } 29 | 30 | put(data) { 31 | const pos = this.hash(data); 32 | this.table[pos] = data; 33 | } 34 | 35 | get(key) { 36 | return this.table[this.hash(key)]; 37 | } 38 | } 39 | 40 | // HashTable with Build Chains technique class example for exercise 2 41 | class HashTableChains extends HashTable { 42 | constructor() { 43 | super(); 44 | this.buildChains(); 45 | } 46 | buildChains() { 47 | for (var i = 0; i < this.table.length; i++) { 48 | this.table[i] = new Array(); 49 | } 50 | } 51 | 52 | showDistro() { 53 | for (const key in this.table) { 54 | if(this.table[key][0] !== undefined) { 55 | console.log(key, ' : ', this.table[key]); 56 | } 57 | } 58 | } 59 | 60 | put(key, data) { 61 | const pos = this.hash(key); 62 | let index = 0; 63 | if(this.table[pos][index] === undefined) { 64 | this.table[pos][index] = data; 65 | } else { 66 | ++index; 67 | while (this.table[pos][index] !== undefined ) { 68 | index++; 69 | } 70 | this.table[pos][index] = data; 71 | } 72 | } 73 | 74 | get(key) { 75 | const pos = this.hash(key); 76 | let index = 0; 77 | while (this.table[pos][index] != key) { 78 | if(this.table[pos][index] !== undefined) { 79 | return this.table[pos][index] 80 | } else { 81 | return undefined; 82 | } 83 | index++; 84 | } 85 | } 86 | } 87 | 88 | // HashTable with Linear Probing technique class example for exercise 1 89 | class HashTableLinearP extends HashTable { 90 | constructor() { 91 | super(); 92 | this.values = new Array(); 93 | } 94 | 95 | put(key, data) { 96 | const pos = this.hash(key); 97 | if(this.table[pos] === undefined) { 98 | this.table[pos] = key; 99 | this.values[pos] = data; 100 | } else { 101 | while(this.table[pos] !== undefined) { 102 | pos++; 103 | } 104 | this.table[pos] = key; 105 | this.values[pos] = data; 106 | } 107 | } 108 | 109 | get(key) { 110 | const hash = this.hash(key); 111 | if (hash > -1) { 112 | for (let i = hash; this.table[i] !== undefined; i++) { 113 | if (this.table[i] === key) { 114 | return this.values[i]; 115 | } 116 | } 117 | } 118 | return undefined; 119 | } 120 | 121 | showDistro() { 122 | for (const key in this.table) { 123 | if(this.table[key] !== undefined) { 124 | console.log(key, ' : ', this.values[key]); 125 | } 126 | } 127 | } 128 | } 129 | 130 | // Implementation 131 | // ################################################# 132 | console.log('CHAPTER 8'); 133 | 134 | const readline = require('readline'); 135 | const fs = require('fs'); 136 | 137 | const hash1 = new HashTableLinearP(); 138 | const hash2 = new HashTableChains(); 139 | 140 | const rl = readline.createInterface({ 141 | input: fs.createReadStream('words.txt') 142 | }); 143 | 144 | rl.on('line', (line) => { 145 | const split = line.split(':'); 146 | hash1.put(split[0], split[1]); 147 | hash2.put(split[0], split[1]); 148 | }); 149 | 150 | rl.on('close', () => { 151 | /* 152 | 1. Use linear probing to create a simple dictionary to store the definitions of words. 153 | Reads a text file that contains a list of words and definitions and stores them in a hash table. 154 | */ 155 | console.log('### Exercise 1'); 156 | hash1.showDistro(); 157 | /* 158 | 2. Repeat exercise 1 using separate chaining. 159 | */ 160 | console.log('\n\n### Exercise 2'); 161 | hash2.showDistro(); 162 | 163 | }); 164 | -------------------------------------------------------------------------------- /10-chapter-Binary-Tree/index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {tree} = require('./tree.module') 3 | Object.assign(exports, {tree}) 4 | }((typeof module.exports !== undefined) ? module.exports : window)) 5 | -------------------------------------------------------------------------------- /10-chapter-Binary-Tree/readme.md: -------------------------------------------------------------------------------- 1 | # Binary Tree and Binary Search Tree 2 | 3 | ### Code Examples 4 | - [Binary Tree Structure](./tree.module.js) 5 | - [Import Module](./index.js) 6 | 7 | ### Description 8 | 9 | `Binary trees` are chosen over other more primary data structures because you can search a binary tree very quickly (as opposed to a linked list, for example) and you can quickly insert and delete data from a binary tree (as opposed to an array). 10 | 11 | common operations you can perform on graphs: 12 | 13 | **Additions** 14 | - `insert`: insert a node to tree, if the node is lower than the root it place it to left otherwise to the right 15 | 16 | **Removals** 17 | 18 | - `remove`: removes a node from the tree 19 | 20 | **Search** 21 | 22 | - `find`: Search for a specific value 23 | - `maxValue`: Search for the minimum value 24 | - `minValue`: Search for the maximum value 25 | 26 | **Traversals** 27 | 28 | - `inOrder`: In this traversal method, the left subtree is visited first, then the root and later the right sub-tree 29 | - `preOrder`: In this traversal method, the root node is visited first, then the left subtree and finally the right subtree. 30 | - `postOrder`: In this traversal method, the root node is visited last, hence the name. First we traverse the left subtree, then the right subtree and finally the root node. 31 | 32 | ![](https://blog.penjee.com/wp-content/uploads/2015/11/binary-search-tree-sorted-array-animation.gif) 33 | 34 | 35 | **Display** 36 | 37 | - `show`: displays the node data 38 | 39 | 40 | ### Example Use Cases: 41 | 42 | - Binary Search Tree - Used in many search applications where data is constantly entering/leaving, such as the map and set objects in many languages' libraries. 43 | - Binary Space Partition - Used in almost every 3D video game to determine what objects need to be rendered. 44 | - Binary Trees - Used in almost every high-bandwidth router for storing router-tables. 45 | - Hash Trees - used in p2p programs and specialized image-signatures in which a hash needs to be verified, but the whole file is not available. 46 | - Heaps - Used in implementing efficient priority-queues, which in turn are used for scheduling processes in many operating systems, Quality-of-Service in routers, and A* (path-finding algorithm used in AI applications, including robotics and video games). Also used in heap-sort. 47 | -------------------------------------------------------------------------------- /10-chapter-Binary-Tree/test.js: -------------------------------------------------------------------------------- 1 | const {tree} = require('./index') 2 | 3 | const nums = tree() 4 | nums.insert(23) 5 | nums.insert(45) 6 | nums.insert(16) 7 | nums.insert(37) 8 | nums.insert(3) 9 | nums.insert(99) 10 | nums.insert(22) 11 | 12 | console.log('Inorder traversal: ') 13 | nums.inOrder(nums.getRoot()) 14 | console.log('\nPreorder traversal: ') 15 | nums.preOrder(nums.getRoot()) 16 | console.log('\nPostorder traversal: ') 17 | nums.postOrder(nums.getRoot()) 18 | console.log(`Find value 45: `) 19 | console.log(nums.find(45)) 20 | 21 | test('Binary tree', assert => { 22 | assert.equal(nums.totalNodes(), 7, `Total of nodes is ${nums.totalNodes()}`) 23 | assert.equal(nums.totalEdges(nums.getRoot()), 4, `Total of edges is ${nums.totalEdges(nums.getRoot())}`) 24 | assert.equal(nums.maxValue(), 99, `Max value of the tree is ${nums.maxValue()}`) 25 | assert.equal(nums.minValue(), 3, `Min value of the tree is ${nums.minValue()}`) 26 | }) 27 | -------------------------------------------------------------------------------- /10-chapter-Binary-Tree/tree.module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const tree = (r = null, n = 0) => { 3 | let nodes = n 4 | let root = r 5 | 6 | const node = (data, left = null, right = null) => { 7 | const o = { 8 | left: null, 9 | right: null, 10 | show () { 11 | console.log(this.data) 12 | } 13 | } 14 | return Object.assign(Object.create(o), {data, left, right}) 15 | } 16 | 17 | const traversals = { 18 | find (data) { 19 | let current = root 20 | while ((current.data !== data)) { 21 | if (data < current.data) { 22 | current = current.left 23 | } else { 24 | current = current.right 25 | } 26 | if (current === null) { 27 | return undefined 28 | } 29 | } 30 | return current 31 | }, 32 | inOrder: function inOrder (node) { 33 | if (!(node === null)) { 34 | inOrder(node.left) 35 | node.show() 36 | inOrder(node.right) 37 | } 38 | }, 39 | preOrder: function preOrder (node) { 40 | if (!(node === null)) { 41 | node.show() 42 | preOrder(node.left) 43 | preOrder(node.right) 44 | } 45 | }, 46 | postOrder: function postOrder (node) { 47 | if (!(node === null)) { 48 | postOrder(node.left) 49 | postOrder(node.right) 50 | node.show() 51 | } 52 | } 53 | } 54 | 55 | const getValues = { 56 | minValue () { 57 | let current = root 58 | while (!(current.left === null)) { 59 | current = current.left 60 | } 61 | return current.data 62 | }, 63 | maxValue () { 64 | let current = root 65 | while (!(current.right === null)) { 66 | current = current.right 67 | } 68 | return current.data 69 | }, 70 | totalNodes: () => nodes, 71 | totalEdges: function totalEdges (node) { 72 | if (node === null) { 73 | return 0 74 | } 75 | if (node.left === null && node.right === null) { 76 | return 1 77 | } else { 78 | return totalEdges(node.left) + totalEdges(node.right) 79 | } 80 | }, 81 | getRoot: () => root 82 | } 83 | 84 | const insert = (data) => { 85 | const n = node(data) 86 | if (root == null) { 87 | root = n 88 | } else { 89 | let current = root 90 | while (!(current === null)) { 91 | let parent = current 92 | if (data < current.data) { 93 | current = current.left 94 | if (current === null) { 95 | parent.left = n 96 | } 97 | } else { 98 | current = current.right 99 | if (current === null) { 100 | parent.right = n 101 | } 102 | } 103 | } 104 | } 105 | nodes += 1 106 | } 107 | 108 | const remove = (data) => { 109 | root = removeNode(getValues.getRoot(), data) 110 | } 111 | 112 | const removeNode = (node, data) => { 113 | if (node === null) { 114 | return null 115 | } 116 | if (data === node.data) { 117 | if (node.left === null && node.right === null) { 118 | return null 119 | } 120 | if (node.left === null) { 121 | return node.right 122 | } 123 | if (node.right === null) { 124 | return node.left 125 | } 126 | 127 | let tempNode = getValues.minValue(node.right) 128 | node.data = tempNode.data 129 | node.right = removeNode(node.right, data) 130 | return node 131 | } else if (data < node.data) { 132 | node.left = removeNode(node.left, data) 133 | } else { 134 | node.right = removeNode(node.right, data) 135 | return node 136 | } 137 | } 138 | 139 | return Object.assign({}, {insert}, {remove}, traversals, getValues) 140 | } 141 | 142 | Object.assign(exports, {tree}) 143 | }((typeof exports !== undefined) ? exports : window)) 144 | -------------------------------------------------------------------------------- /11-chapter-Graphs/graph.module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {bfs, dfs} = require('./graph.search') 3 | 4 | const graphFactory = () => { 5 | let graph = {} 6 | let vertices = 0 7 | 8 | const graphProto = { 9 | contains: (node) => !!graph[node], 10 | hasEdge: (nodeOne, nodeTwo) => { 11 | if (graphProto.contains(nodeOne) && graphProto.contains(nodeTwo)) { 12 | return !!graph[nodeOne].edges[nodeTwo] 13 | } 14 | }, 15 | addVertex: (node) => { 16 | if (!graphProto.contains(node)) { 17 | graph[node] = {edges: {}, visited: false} 18 | vertices += 1 19 | } 20 | }, 21 | removeVertex: (node) => { 22 | if (graphProto.contains(node)) { 23 | for (let item in graph[node].edges) { 24 | if (graph[node].edges.hasOwnProperty(item)) { 25 | graph.removeEdge(node, item) 26 | } 27 | } 28 | vertices -= 1 29 | delete graph[node] 30 | } 31 | }, 32 | addEdge: (nodeOne, nodeTwo) => { 33 | if (graphProto.contains(nodeOne) && graphProto.contains(nodeTwo)) { 34 | graph[nodeOne].edges[nodeTwo] = true 35 | graph[nodeTwo].edges[nodeOne] = true 36 | } 37 | }, 38 | removeEdge: (nodeOne, nodeTwo) => { 39 | if (graphProto.contains(nodeOne) && graphProto.contains(nodeTwo)) { 40 | delete graph[nodeOne].edges[nodeTwo] 41 | delete graph[nodeTwo].edges[nodeOne] 42 | } 43 | }, 44 | showGraph: () => { 45 | let show = '' 46 | for (let v in graph) { 47 | show += `${v} -> ` 48 | for (let n in graph[v].edges) { 49 | show += n + ', ' 50 | } 51 | show += '\n' 52 | } 53 | console.log(show) 54 | }, 55 | showVertex: (node) => console.log(graphProto.getVertex(node)), 56 | showVertexs: () => console.log(Object.keys(graph)), 57 | getGraph: () => graph, 58 | getVertex: (node) => (graphProto.contains(node)) ? graph[node] : false, 59 | getNumVertices: () => vertices 60 | } 61 | 62 | Object.assign(graphProto, {bfs: bfs.bind(graphProto), dfs: dfs.bind(graphProto)}) 63 | 64 | return Object.create(graphProto) 65 | } 66 | 67 | Object.assign(exports, {graph: graphFactory}) 68 | }((typeof module.exports !== undefined) ? module.exports : window)) 69 | -------------------------------------------------------------------------------- /11-chapter-Graphs/graph.search.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {stack} = require('../04-chapter-Stack/') 3 | const {queue} = require('../05-chapter-Queue/') 4 | let graph 5 | let keys 6 | 7 | const displayVertex = (node) => console.log(node) 8 | 9 | const getUnvistedVertex = (vertex) => { 10 | for (let node in graph[vertex].edges) { 11 | if (graph[node].visited === false) { 12 | return node 13 | } 14 | } 15 | return false 16 | } 17 | 18 | const resetSearch = () => { 19 | for (let node in graph) { 20 | graph[node].visited = false 21 | } 22 | } 23 | 24 | function dfs () { 25 | graph = this.getGraph() 26 | keys = Object.keys(graph) 27 | let graphStack = stack() 28 | graph[keys[0]].visited = true 29 | displayVertex(keys[0]) 30 | graphStack.push(keys[0]) 31 | 32 | while (!graphStack.isEmpty()) { 33 | let unvistedVertex = getUnvistedVertex(graphStack.peek()) 34 | 35 | if (unvistedVertex === false) { 36 | graphStack.pop() 37 | } else { 38 | graph[unvistedVertex].visited = true 39 | displayVertex(unvistedVertex) 40 | graphStack.push(unvistedVertex) 41 | } 42 | } 43 | 44 | resetSearch() 45 | } 46 | 47 | function bfs () { 48 | graph = this.getGraph() 49 | keys = Object.keys(graph) 50 | let unvistedVertex 51 | let graphQueue = queue() 52 | graph[keys[0]].visited = true 53 | displayVertex(keys[0]) 54 | graphQueue.enqueue(keys[0]) 55 | 56 | while (!graphQueue.isEmpty()) { 57 | let tempVertex = graphQueue.dequeue() 58 | unvistedVertex = getUnvistedVertex(tempVertex) 59 | 60 | while (unvistedVertex !== false) { 61 | graph[unvistedVertex].visited = true 62 | displayVertex(unvistedVertex) 63 | graphQueue.enqueue(unvistedVertex) 64 | unvistedVertex = getUnvistedVertex(tempVertex) 65 | } 66 | } 67 | 68 | resetSearch() 69 | } 70 | 71 | Object.assign(exports, {dfs, bfs}) 72 | }((typeof module.exports !== undefined) ? module.exports : window)) 73 | -------------------------------------------------------------------------------- /11-chapter-Graphs/readme.md: -------------------------------------------------------------------------------- 1 | # Graph Data Structure 2 | 3 | ### Code Examples 4 | - [Graph Data Structure](./graph.module.js) 5 | - [Graph Search Algorithms](./graph.search.js) 6 | - [Import Module](./index.js) 7 | 8 | ### Description 9 | 10 | There are two main parts of a graph: 11 | 12 | - The **vertices** (nodes) where the data is stored i.e. the numbers in the image 13 | - The **edges** (connections) which connect the nodes i.e. the lines between the numbers in the image 14 | 15 | ![](https://cdn-images-1.medium.com/max/600/0*cqxOTC4NOK62xow1.png) 16 | 17 | Graphs can be **undirected** or **directed** 18 | 19 | - Undirected graph: The relationship exists in both directions. 20 | - Directed graph: The relationships are based on the direction of the edges. It can be a one way relationship or a two-way relationship, but it must be explicitly stated. 21 | 22 | common operations you can perform on graphs: 23 | 24 | **Additions** 25 | 26 | - `addNode`: adds vertices to your graph 27 | - `addEdge`: creates edges between two given vertices in your graph 28 | 29 | **Removals** 30 | 31 | - `removeNode`: removes vertices from your graph 32 | - `removeEdge`: removes edges between two given vertices in your graph 33 | 34 | **Search** 35 | 36 | - `contains`: checks if your graph contains a given value 37 | - `hasEdge`: checks if a connection exists between two given nodes in your graph 38 | - `dfs`: Depth First Search (DFS) algorithm traverses a graph in a depthward motion and uses a stack to remember to get the next vertex to start a search, when a dead end occurs in any iteration. 39 | - `bfs`: Breadth First Search (BFS) algorithm traverses a graph in a breadthward motion and uses a queue to remember to get the next vertex to start a search, when a dead end occurs in any iteration. 40 | 41 | ![](https://i2.wp.com/codingsec.net/wp-content/uploads/2016/03/dfs-bfs-codingsec.gif) 42 | 43 | 44 | **Display** 45 | 46 | - `showGraph`: displays the complete graph 47 | - `showVertex`: displays one vertex 48 | - `showVertexs`: displays all the vertexs in the graph 49 | 50 | In addition to this, graphs can be weighted or unweighted. All this means is that there is some value or cost associated with the edges between the vertices. 51 | 52 | ### Example Use Cases: 53 | 54 | - Electrical Engineering − The concepts of graph theory is used extensively in designing circuit connections. The types or organization of connections are named as topologies. Some examples for topologies are star, bridge, series, and parallel topologies. 55 | 56 | - Computer Science − Graph theory is used for the study of algorithms. For example, 57 | 58 | - Kruskal's Algorithm 59 | - Prim's Algorithm 60 | - Dijkstra's Algorithm 61 | 62 | - Computer Network − The relationships among interconnected computers in the network follows the principles of graph theory. 63 | 64 | - Science − The molecular structure and chemical structure of a substance, the DNA structure of an organism, etc., are represented by graphs. 65 | 66 | - Linguistics − The parsing tree of a language and grammar of a language uses graphs. 67 | 68 | - General − Routes between the cities can be represented using graphs. Depicting hierarchical ordered information such as family tree can be used as a special type of graph called tree. 69 | Graphs are used to model many different types of real-world systems. 70 | 71 | Another example of a real word system that can be modeled by a graph is a consumer market, where vertices represent both institutions (vendors) and consumers. 72 | 73 | ### References 74 | 75 | - [A Gentle Introduction to Data Structures: How Graphs Work](https://medium.freecodecamp.com/a-gentle-introduction-to-data-structures-how-graphs-work-a223d9ef8837#.ojpoqfcxa) 76 | - [Data Structure - Graph Data Structure](https://www.tutorialspoint.com/data_structures_algorithms/graph_data_structure.htm) 77 | -------------------------------------------------------------------------------- /11-chapter-Graphs/test.js: -------------------------------------------------------------------------------- 1 | const {graph} = require('./graph.module') 2 | 3 | test('Graph Data Structure', assert => { 4 | const devBook = graph() 5 | const devBook2 = graph() 6 | 7 | devBook.addVertex('S') 8 | devBook.addVertex('A') 9 | devBook.addVertex('B') 10 | devBook.addVertex('C') 11 | devBook.addVertex('D') 12 | devBook.addVertex('E') 13 | 14 | assert.equal(!!devBook.getVertex('A'), true, 'adds vertex') 15 | 16 | devBook.addEdge('S', 'A') 17 | devBook.addEdge('S', 'B') 18 | devBook.addEdge('S', 'C') 19 | devBook.addEdge('A', 'D') 20 | devBook.addEdge('B', 'D') 21 | devBook.addEdge('C', 'D') 22 | devBook.addEdge('A', 'E') 23 | 24 | const vertex = devBook.getVertex('A') 25 | 26 | assert.equal(vertex, devBook.getVertex('A'), 'get vertex object') 27 | 28 | assert.equal(devBook.getVertex('C').edges['D'], true, 'adds edges') 29 | 30 | devBook.removeEdge('A', 'E') 31 | 32 | assert.equal(!!devBook.getVertex('A').edges['E'], false, 'removes an edge') 33 | 34 | devBook.removeVertex('E') 35 | 36 | assert.equal(devBook.getVertex('E'), false, 'removes a vertex') 37 | 38 | assert.ok(devBook.hasEdge('B', 'D'), 'verify has edge') 39 | 40 | devBook.showGraph() 41 | 42 | devBook.showVertexs() 43 | 44 | console.log('DFS() search...') 45 | 46 | devBook.dfs() 47 | 48 | console.log('BFS() search...') 49 | 50 | devBook.bfs() 51 | 52 | devBook2.addVertex('F') 53 | devBook2.addVertex('G') 54 | devBook2.addVertex('H') 55 | devBook2.addVertex('I') 56 | devBook2.addVertex('J') 57 | devBook2.addEdge('F', 'G') 58 | devBook2.addEdge('F', 'H') 59 | devBook2.addEdge('F', 'I') 60 | devBook2.addEdge('G', 'J') 61 | devBook2.addEdge('H', 'J') 62 | devBook2.addEdge('I', 'J') 63 | 64 | devBook2.showGraph() 65 | 66 | devBook2.showVertexs() 67 | 68 | console.log('DFS() search...') 69 | 70 | devBook2.dfs() 71 | 72 | console.log('BFS() search...') 73 | 74 | devBook2.bfs() 75 | }) 76 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/basic-sort.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | let alist, swap 3 | 4 | function bubbleSort () { 5 | const numElements = alist.length 6 | for (let outer = numElements; outer >= 2; outer--) { 7 | for (let inner = 0; inner <= outer - 1; inner++) { 8 | if (alist[inner] > alist[inner + 1]) { 9 | swap(inner, inner + 1) 10 | } 11 | } 12 | } 13 | } 14 | 15 | function selectionSort () { 16 | let min 17 | for (let outer = 0; outer <= alist.length - 2; outer++) { 18 | min = outer 19 | for (let inner = outer + 1; inner <= alist.length - 1; inner++) { 20 | if (alist[inner] < alist[min]) { 21 | min = inner 22 | } 23 | } 24 | swap(outer, min) 25 | } 26 | } 27 | 28 | function insertionSort () { 29 | let temp 30 | let inner 31 | 32 | for (let outer = 1; outer <= alist.length - 1; outer++) { 33 | temp = alist[outer] 34 | inner = outer 35 | while (inner > 0 && (alist[inner - 1] >= temp)) { 36 | alist[inner] = alist[inner - 1] 37 | --inner 38 | } 39 | alist[inner] = temp 40 | } 41 | } 42 | 43 | const bubbleObject = { 44 | sort (args) { 45 | swap = [].slice.call(arguments, 1)[0] 46 | alist = args 47 | bubbleSort(0, alist.length - 1) 48 | return alist 49 | } 50 | } 51 | 52 | const selectionObject = { 53 | sort (...args) { 54 | alist = args[0] 55 | swap = args[1] 56 | selectionSort(0, alist.length - 1) 57 | return alist 58 | } 59 | } 60 | 61 | const insertionObject = { 62 | sort (args) { 63 | alist = args 64 | insertionSort(0, alist.length - 1) 65 | return alist 66 | } 67 | } 68 | 69 | Object.assign( 70 | exports, 71 | {bubbleSort: bubbleObject}, 72 | {selectionSort: selectionObject}, 73 | {insertionSort: insertionObject} 74 | ) 75 | }((typeof module.exports !== undefined) ? module.exports : window)) 76 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const sort = require('./sort-module') 3 | Object.assign(exports, sort) 4 | }((typeof module.exports !== undefined) ? module.exports : window)) 5 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/merge-sort.module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | let alist 3 | 4 | function mergeSort () { 5 | if (alist.length < 2) { 6 | return 7 | } 8 | 9 | let left, right 10 | let step = 1 11 | 12 | while (step < alist.length) { 13 | left = 0 14 | right = step 15 | while (right + step <= alist.length) { 16 | mergeArrays(left, left + step, right, right + step) 17 | left = right + step 18 | right = left + step 19 | } 20 | if (right < alist.length) { 21 | mergeArrays(left, left + step, right, alist.length) 22 | } 23 | step *= 2 24 | } 25 | } 26 | 27 | function mergeArrays (startLeft, stopLeft, startRight, stopRight) { 28 | let rightArr = new Array(stopRight - startRight + 1) 29 | let leftArr = new Array(stopLeft - startLeft + 1) 30 | let k = startRight 31 | let m = 0 32 | let n = 0 33 | 34 | for (let i = 0; i < rightArr.length - 1; i++) { 35 | rightArr[i] = alist[k] 36 | ++k 37 | } 38 | 39 | k = startLeft 40 | for (let i = 0; i < leftArr.length - 1; i++) { 41 | leftArr[i] = alist[k] 42 | k++ 43 | } 44 | 45 | rightArr[rightArr.length - 1] = Infinity // a sentinel value 46 | leftArr[leftArr.length - 1] = Infinity // a sentinel value 47 | 48 | for (k = startLeft; k < stopRight; k++) { 49 | if (leftArr[m] <= rightArr[n]) { 50 | alist[k] = leftArr[m] 51 | m++ 52 | } else { 53 | alist[k] = rightArr[n] 54 | n++ 55 | } 56 | } 57 | } 58 | 59 | const mergeObject = { 60 | sort (args) { 61 | alist = args 62 | mergeSort() 63 | return alist 64 | } 65 | } 66 | 67 | Object.assign(exports, {mergeSort: mergeObject}) 68 | }((typeof module.exports !== undefined) ? module.exports : window)) 69 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/quick-sort.module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | let alist, swap 3 | 4 | function quickSortHelper (left, right) { 5 | if (right - left <= 0) { 6 | return 7 | } else { 8 | const pivot = alist[right] 9 | const splitPoint = partition(left, right, pivot) 10 | quickSortHelper(left, splitPoint - 1) 11 | quickSortHelper(splitPoint + 1, right) 12 | } 13 | } 14 | 15 | function partition (left, right, pivot) { 16 | let leftmark = left - 1 17 | let rightmark = right 18 | 19 | while (true) { 20 | while (alist[++leftmark] < pivot) {} 21 | while (rightmark > 0 && alist[--rightmark] > pivot) {} 22 | if (rightmark <= leftmark) { 23 | break 24 | } else { 25 | swap(leftmark, rightmark) 26 | } 27 | } 28 | 29 | swap(leftmark, right) 30 | return leftmark 31 | } 32 | 33 | const quickObject = { 34 | sort (...args) { 35 | alist = args[0] 36 | swap = args[1] 37 | quickSortHelper(0, alist.length - 1) 38 | return alist 39 | } 40 | } 41 | 42 | Object.assign(exports, {quickSort: quickObject}) 43 | }((typeof module.exports !== undefined) ? module.exports : window)) 44 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/readme.md: -------------------------------------------------------------------------------- 1 | # Sort Algorithms with ES6 2 | 3 | ### Code Examples 4 | - [Basic Sorting Algorithms](./basic-sort.js) 5 | - [Advanced Sorting Algorithms - Quick Sort](./quick-sort.module.js) 6 | - [Advanced Sorting Algorithms - Merge Sort](./merge-sort.module.js) 7 | - [Module](./sort-module.js) 8 | - [Implentation](./implementation.js) 9 | - [Import Module](./index.js) 10 | 11 | ### Description 12 | 13 | Sorting is the most heavily studied concept in Computer Science. A sorting algorithm takes a list of items and sorts them in a particular order, most commonly alphabetically or numerical. Though every major programming language has built-in sorting libraries, it comes in handy if you know how they work. Depending upon requirement you may want to use any of these. 14 | 15 | **Bubble Sort** 16 | 17 | The bubble sort is one of the slowest sorting algorithms, but it is also one of the easiest sorts to implement. 18 | 19 | ![](https://upload.wikimedia.org/wikipedia/commons/c/c8/Bubble-sort-example-300px.gif) 20 | 21 | **Selection Sort** 22 | 23 | This sort works by starting at the beginning of the array and comparing the first element with the remaining elements. After examining all the elements, the smallest element is placed in the first position of the array, and the algorithm moves to the second position. This process continues until the data is sorted. 24 | 25 | ![](https://upload.wikimedia.org/wikipedia/commons/9/94/Selection-Sort-Animation.gif) 26 | 27 | **Insertion Sort** 28 | 29 | Insertion sort is a simple sorting algorithm that builds the final sorted array (or list) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. However, insertion sort provides several advantages. 30 | 31 | ![](https://upload.wikimedia.org/wikipedia/commons/0/0f/Insertion-sort-example-300px.gif) 32 | 33 | **Quick Sort** 34 | 35 | The Quicksort algorithm is one of the fastest sorting algorithms for large data sets. Quicksort is a divide-and-conquer algorithm that recursively breaks a list of data into successively smaller sublists consisting of the smaller elements and the larger elements. The algorithm continues this process until all the data in the list is sorted. The algorithm divides the list into sublists by selecting one element of the list as a pivot. Data is sorted around the pivot by moving elements less than the pivot to the bottom of the list and elements that are greater than the pivot to the top of the list. 36 | 37 | ![](https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif) 38 | 39 | **Merge Sort** 40 | 41 | MergeSort is a Divide and Conquer algorithm. It divides input array in two halves, calls itself for the two halves and then merges the two sorted halves. The merge() function is used for merging two halves. The merge(arr, l, m, r) is key process that assumes that arr[l..m] and arr[m+1..r] are sorted and merges the two sorted sub-arrays into one. 42 | 43 | ![](https://upload.wikimedia.org/wikipedia/commons/c/cc/Merge-sort-example-300px.gif) 44 | 45 | **Bucket** and **Heap** sort makes use of insertion sort function help, to sort the elements. But this methods are usefull and import anyway. 46 | 47 | 48 | #### Properties of a sorting algorithm 49 | 50 | In addition to the time and space complexity of sorting algorithms, the below properties help define sorting algorithms. 51 | 52 | |Property | Description | 53 | | --- | --- | 54 | |Adaptability | An adaptive sort’s performance improves the more sorted the list is initially. 55 | |In-place | An in-place sort requires a constant amount of additional space. 56 | |Parallelism | A parallel sort can split its workload between multiple workers. 57 | |Stability | A stable sort preserves the order of items in the list that evaluate to the same value. 58 | 59 | More importantly one should know when and where to use them. Some examples where you can find direct application of sorting techniques include: 60 | 61 | Sorting by price, popularity etc in e-commerce websites 62 | 63 | #### Resources 64 | 65 | - Images from wikipedia 66 | - [More information about Sorting Algorithms](http://www.growingwiththeweb.com/2014/06/sorting-algorithms.html) 67 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/sort-module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {quickSort: quickMethod} = require('./quick-sort.module') 3 | const {mergeSort: mergeMethod} = require('./merge-sort.module') 4 | const {bubbleSort, selectionSort, insertionSort} = require('./basic-sort') 5 | 6 | let alist 7 | 8 | const display = () => console.log(alist) 9 | 10 | const getData = () => alist 11 | 12 | function swap (v1, v2) { 13 | const temp = alist[v1] 14 | alist[v1] = alist[v2] 15 | alist[v2] = temp 16 | } 17 | 18 | const methods = { 19 | bubbleSort () { 20 | alist = bubbleSort.sort(alist, swap) 21 | return this.getData() 22 | }, 23 | selectionSort () { 24 | alist = selectionSort.sort(alist, swap) 25 | return this.getData() 26 | }, 27 | insertionSort () { 28 | alist = insertionSort.sort(alist) 29 | return this.getData() 30 | }, 31 | quickSort () { 32 | alist = quickMethod.sort(alist, swap) 33 | return this.getData() 34 | }, 35 | mergeSort () { 36 | alist = mergeMethod.sort(alist) 37 | return this.getData() 38 | }, 39 | getData, 40 | display 41 | } 42 | 43 | exports.sort = function sort (args) { 44 | alist = args 45 | Object.assign(this, methods) 46 | return this 47 | } 48 | }((typeof module.exports !== undefined) ? module.exports : window)) 49 | -------------------------------------------------------------------------------- /12-chapter-Sorting-Algorithms/test.js: -------------------------------------------------------------------------------- 1 | const {sort} = require('./sort-module') 2 | 3 | const nsTime = (hrtime) => hrtime[0] * 1e9 + hrtime[1] 4 | 5 | function setData (numElements = 100) { 6 | let dataStore = [] 7 | for (let i = 0; i < numElements; i++) { 8 | dataStore[i] = Math.floor(Math.random() * (numElements + 1)) 9 | } 10 | return dataStore 11 | } 12 | 13 | let basic = 50 14 | 15 | test (`bubbleSort test with ${basic} elements`, assert => { 16 | let start = process.hrtime() 17 | let dataStore = setData(basic) 18 | let sorted = sort(dataStore).bubbleSort() 19 | let end = process.hrtime(start) 20 | 21 | assert.equal(dataStore.sort(), sorted, `Elapsed time on ${basic} elements is: ${nsTime(end) / 1e9} seconds.`) 22 | }) 23 | 24 | test (`selectionSort test with ${basic} elements`, assert => { 25 | let start = process.hrtime() 26 | let dataStore = setData(basic) 27 | let sorted = sort(dataStore).selectionSort() 28 | let end = process.hrtime(start) 29 | 30 | assert.equal(dataStore.sort(), sorted, `Elapsed time on ${basic} elements is: ${nsTime(end) / 1e9} seconds.`) 31 | }) 32 | 33 | test (`insertionSort test with ${basic} elements`, assert => { 34 | let start = process.hrtime() 35 | let dataStore = setData(basic) 36 | let sorted = sort(dataStore).insertionSort() 37 | let end = process.hrtime(start) 38 | 39 | assert.equal(dataStore.sort(), sorted, `Elapsed time on ${basic} elements is: ${nsTime(end) / 1e9} seconds.`) 40 | }) 41 | 42 | let advance = 1000 43 | 44 | test (`mergeSort test with ${advance} elements`, assert => { 45 | let start = process.hrtime() 46 | let dataStore = setData(advance) 47 | let sorted = sort(dataStore).mergeSort() 48 | let end = process.hrtime(start) 49 | 50 | assert.equal(dataStore.sort(), sorted, `Elapsed time on ${advance} elements is: ${nsTime(end) / 1e9} seconds.`) 51 | }) 52 | 53 | test (`quickSort test with ${advance} elements`, assert => { 54 | let start = process.hrtime() 55 | let dataStore = setData(advance) 56 | let sorted = sort(dataStore).quickSort() 57 | let end = process.hrtime(start) 58 | 59 | assert.equal(dataStore.sort(), sorted, `Elapsed time on ${advance} elements is: ${nsTime(end) / 1e9} seconds.`) 60 | }) 61 | -------------------------------------------------------------------------------- /13-chapter-Searching-Algorithms/index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const search = require('./search-module') 3 | Object.assign(exports, {search}) 4 | }((typeof module.exports !== undefined) ? module.exports : window)) 5 | -------------------------------------------------------------------------------- /13-chapter-Searching-Algorithms/paragraph.txt: -------------------------------------------------------------------------------- 1 | The nationalism of Hamilton was undemocratic. The democracy of Jefferson was, 2 | in the beginning, provincial. The historic mission of uniting nationalism and democracy was in the course of time given to new leaders from a region beyond the mountains, peopled by men and women from all sections and free from those state traditions which ran back to the early days of colonization. The voice 3 | of the democratic nationalism nourished in the West was heard when Clay of Kentucky advocated his American system of protection for industries; when Jackson of Tennessee condemned nullification in a ringing proclamation that 4 | has taken its place among the great American state papers; and when Lincoln 5 | of Illinois, in a fateful hour, called upon a bewildered people to meet the supreme test whether this was a nation destined to survive or to perish. And 6 | it will be remembered that Lincoln's party chose for its banner that earlier device--Republican--which Jefferson had made a sign of power. The "rail splitter" from Illinois united the nationalism of Hamilton with the democracy of Jefferson, and his appeal was clothed in the simple language of the people, not in the sonorous rhetoric which Webster learned in the schools. 7 | -------------------------------------------------------------------------------- /13-chapter-Searching-Algorithms/readme.md: -------------------------------------------------------------------------------- 1 | # Search Algorithms with ES6 2 | 3 | ### Code Examples 4 | 5 | - [Sequential/Binary Search example](./search-module.js) 6 | - [JavaScript built-in findIndex(), find()](../03-chapter-List.js) 7 | - [Binary Search Tree Searches](../10-chapter-Binary-Trees.js) 8 | - [Depth/Breadth First Search](../11-chapter-2-adjecency-list-Graphs.js) 9 | 10 | ### Description 11 | 12 | There are two ways to search for data in a list: sequential search and binary search. A sequential search is used when the items in a list are in random order; a binary search is used when the items in a list are in sorted order. Binary search is the more efficient algorithm, but you also have to take into account the extra time it takes to sort the data set before being able to search it for a value. 13 | 14 | JavaScript has built-in functions for searching values in an array, that are the following: 15 | 16 | - indexOf() returns the index of the value to find if the value exists otherwise returns -1. 17 | - find() returns true if the value exists otherwise returns false. 18 | - findIndex() return the same as indexOf. 19 | 20 | find() and findIndex() are ES6 features and needs extra parameters to perform the search. 21 | 22 | **Sequential Search** 23 | 24 | The most obvious way to search for data in a list is to begin at the first element and move to each element in the list until you either find the data you are looking for or you reach the end of the list. This is called a sequential search, sometimes also called a linear search. It is an example of a brute-force search technique, where potentially every element in the data structure is visited on the way to a solution. 25 | 26 | **Binary Search** (in linear data structures) 27 | 28 | Binary search is used to perform a very efficient search on sorted dataset. The time complexity is O(log2N). Idea is to repeatedly divide in half the portion of the list that could contain the item, until we narrow it down to one possible item. 29 | 30 | ![](https://blog.penjee.com/wp-content/uploads/2015/04/binary-and-linear-search-animations.gif) 31 | 32 | Some applications are: 33 | 34 | - When you search for a name of song in a sorted list of songs, it performs binary search and string-matching to quickly return the results. 35 | - Used to debug in git through git bisect 36 | 37 | **Searching Textual Data** (in JavaScript) 38 | 39 | breaking up the text into words using the split() function, which uses the space between each word as the delimiter. This code is not perfect because punctuation is left in the file and is stored with the nearest word, but it will suffice for our purposes. Once the textual data is stored in an array, we can begin searching through the array to find words, using Sequential or Binary Search. 40 | 41 | 42 | **Binary Search Tree Searches** 43 | 44 | There are three types of searches typically performed with a BST: 45 | 46 | - Searching for a specific value 47 | - Searching for the minimum value 48 | - Searching for the maximum value 49 | 50 | Searches in a BST for the minimum and maximum values stored are relatively simple procedures. Since lower values are always stored in left child nodes, to find the minimum value in a BST, you only have to traverse the left edge of the BST until you get to the last node. 51 | 52 | To find the maximum value stored in a BST, the function must simply traverse the right links of nodes until the function reaches the right end of the BST. The value stored in this node must be the maximum value. 53 | 54 | Searching for a specific value in a BST requires that a comparison be made between the data stored in the current node and the value being searched for. The comparison will determine if the search travels to the left child node, or to the right child node if the current node doesn’t store the searched-for value. 55 | 56 | ![](https://blog.penjee.com/wp-content/uploads/2015/11/binary-search-tree-sorted-array-animation.gif) 57 | 58 | **Depth/Breadth First Search** (in Graph data structures) 59 | 60 | DFS and BFS are tree/graph traversing and searching data structures. 61 | 62 | Determining which vertices can be reached from a specified vertex is a common activity performed on graphs. We might want to know which roads lead from one town to other towns on the map, or which flights can take us from one airport to other airports. 63 | 64 | These operations are performed on a graph using a search algorithm. There are two fundamental searches we can perform on a graph: the depth-first search and the breadth- first search. 65 | 66 | ![](https://i2.wp.com/codingsec.net/wp-content/uploads/2016/03/dfs-bfs-codingsec.gif) 67 | 68 | Applications: 69 | 70 | - Used by search engines for web-crawling 71 | - Used in artificial intelligence to build bots, for instance a chess bot 72 | - Finding shortest path between two cities in a map and many other such applications 73 | 74 | 75 | #### Resources 76 | 77 | - [7 algorithms and data structures every programmer must know](https://codingsec.net/2016/03/7-algorithms-data-structures-every-programmer/) 78 | -------------------------------------------------------------------------------- /13-chapter-Searching-Algorithms/search-module.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const sequentialSearch = (dataStore, data) => { 3 | for (var i = 0; i < dataStore.length; i++) { 4 | if (dataStore[i] === data) { 5 | return i 6 | } 7 | } 8 | return -1 9 | } 10 | 11 | const binarySearch = (dataStore, data) => { 12 | let upperBound = dataStore.length - 1 13 | let lowerBound = 0 14 | while (lowerBound <= upperBound) { 15 | let mid = Math.floor((lowerBound + upperBound) / 2) 16 | if (dataStore[mid] < data) { 17 | lowerBound = mid + 1 18 | } else if (dataStore[mid] > data) { 19 | upperBound = mid - 1 20 | } else { 21 | return mid 22 | } 23 | } 24 | return -1 25 | } 26 | 27 | const countOccurrences = (dataStore, data) => { 28 | let count = 0 29 | let position = binarySearch(dataStore, data) 30 | if (position > -1) { 31 | count += 1 32 | for (let i = position; i > 0; i--) { 33 | if (dataStore[i] === data) { 34 | count += 1 35 | } else { 36 | break 37 | } 38 | } 39 | for (let i = position + 1; i < dataStore.length; i++) { 40 | if (dataStore[i] === data) { 41 | count += 1 42 | } else { 43 | break 44 | } 45 | } 46 | } 47 | return count 48 | } 49 | 50 | const minValue = (dataStore) => { 51 | let min = dataStore[0] 52 | for (var i = 1; i < dataStore.length; i++) { 53 | if (dataStore[i] < min) { 54 | min = dataStore[i] 55 | } 56 | } 57 | return min 58 | } 59 | 60 | const maxValue = (dataStore) => { 61 | let max = dataStore[0] 62 | for (var i = 1; i < dataStore.length; i++) { 63 | if (dataStore[i] > max) { 64 | max = dataStore[i] 65 | } 66 | } 67 | return max 68 | } 69 | 70 | Object.assign(exports, {sequentialSearch, binarySearch, minValue, maxValue, countOccurrences}) 71 | }((typeof module.exports !== undefined) ? module.exports : window)) 72 | -------------------------------------------------------------------------------- /13-chapter-Searching-Algorithms/test.js: -------------------------------------------------------------------------------- 1 | const {search} = require('./index') 2 | const {sort} = require('../12-chapter-Sorting-Algorithms/') 3 | const fs = require('fs') 4 | 5 | const nsTime = (hrtime) => hrtime[0] * 1e9 + hrtime[1] 6 | 7 | const setData = (numElements = 100) => { 8 | let dataStore = [] 9 | for (let i = 0; i < numElements; i++) { 10 | dataStore[i] = Math.floor(Math.random() * (numElements + 1)) 11 | } 12 | return dataStore 13 | } 14 | 15 | test ('Binary and Sequential search on array of numbers', assert => { 16 | let dataStore = setData() 17 | let number = 11 18 | let result = search.sequentialSearch(dataStore, number) 19 | assert.ok(result, (result >= 0) ? `${number} is present in the set and is in the position ${result}` : 'not generated number') 20 | assert.ok(search.minValue, `The minimum value is: ${search.minValue(dataStore)}`) 21 | assert.ok(search.maxValue, `The maximum value is: ${search.maxValue(dataStore)}`) 22 | dataStore = sort(dataStore).insertionSort() 23 | result = search.binarySearch(dataStore, number) 24 | const count = search.countOccurrences(dataStore, number) 25 | assert.ok((result), (result >= 0) ? `${number} is present in the set and is in the position ${result} and has ${count} occurrences` : 'not generated number') 26 | }) 27 | 28 | test ('Binary and Sequential search on text file', assert => { 29 | let data = fs.readFileSync('./13-chapter-Searching-Algorithms/paragraph.txt', 'utf8') 30 | .trim() 31 | .split(' ') 32 | 33 | const word = 'rhetoric' 34 | let start = process.hrtime() 35 | let position = search.sequentialSearch(data, word) 36 | let end = process.hrtime(start) 37 | 38 | assert.ok(position, `${word} is present in the set and is in the position ${position}`) 39 | assert.ok(position, `Sequential search took ${nsTime(end) / 1e9} milliseconds.`) 40 | 41 | data = sort(data).insertionSort() 42 | start = process.hrtime() 43 | position = search.binarySearch(data, word) 44 | end = process.hrtime(start) 45 | 46 | assert.ok((position >= 0), `${word} is present in the set and is in the position ${position}`) 47 | assert.ok(position, `Binary search took ${nsTime(end) / 1e9} milliseconds.`) 48 | }) 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data Structures and Algorithms with ES6 2 | 3 | ![](https://i.blogs.es/545cf8/es6-logo/original.png) ![](https://lh3.googleusercontent.com/a4Xrc-8oQLu05mOrNPuvA_o2nZEIEnOoTH4wB91Slw_hCvuIu_Qgi440bK9mC8ml-KA=w300) 4 | 5 | ## Examples in this repo 6 | 7 | | **Num** | **Type** | **Exercises** | **Description** | 8 | --- | --- | --- | --- 9 | | 1.- | [Array](./02-chapter-Array) | 4 | The `Array` is the most common data structure in computer programming 10 | | 2.- | [Lists](./03-chapter-List.js) | 5 | A `List` is an ordered sequence of data, where elements are not meant to be ordered. 11 | | 3.- | [Stacks](./04-chapter-Stack) | 3 | A `Stack` is an example of Last-in, First-Out (LIFO) 12 | | 4.- | [Queues](./05-chapter-Queue) | 2 | A `Queue` is an example of First-in, First-Out (FIFO) 13 | | 5.- | [Linked List](./06-chapter-Linked-Lists-types) | 4 | A `Linked list` is a collection of objects called nodes. Each node is linked to a successor node in the list using an object reference. 14 | | 6.- | [Double Linked List](./06-chapter-Linked-Lists-types) | 3 | Traversing a `Double linked list` are more efficient, since we no longer have to search for the previous node. 15 | | 7.- | [Circular Linked List](./06-chapter-Linked-Lists-types) | 4 | The reason you might want to create a `Circular linked list` is if you want the ability to go backward through a list but don’t want the extra overhead of creating a doubly linked list. 16 | | 8.- | [Hashing](./08-chapter-Hashing.js) | 2 | `Hashing` is a common technique for storing data in such a way that the data can be inserted and retrieved very quickly. Hashing uses a data structure called a hash table. Although hash tables provide fast insertion, deletion, and retrieval, they perform poorly for operations that involve searching. 17 | | 9.- | [Binary Trees and Binary Search Trees](./10-chapter-Binary-Tree) | 4 | `Binary trees` are chosen over other more primary data structures because you can search a binary tree very quickly (as opposed to a linked list, for example) and you can quickly insert and delete data from a binary tree (as opposed to an array). 18 | | 10.- | [Graph Data Structure](./11-chapter-Graphs) | 2 | A graph consists of a set of vertices and a set of edges. A map is a type of graph where each town is a vertex, and a road that connects two towns is an edge. Edges are defined as a pair (v1, v2), where v1 and v2 are two vertices in a graph 19 | | 11.- | [Sorting Algorithms](./12-chapter-Sorting-Algorithms) | 6 | Two of the most common operations performed on data stored in a computer are sorting and searching. 20 | | 12.- | [Searching Algorithms](./13-chapter-Searching-Algorithms) | 6 | There are two ways to search for data in a list: sequential search and binary search. A sequential search is used when the items in a list are in random order; a binary search is used when the items in a list are in sorted order. 21 | 22 | 23 | ### To run the examples we need the following: 24 | 25 | - NodeJS Installed 26 | - Open Any Terminal and position it to the folder where the files are located 27 | - execute the tests: `$ npm install` then `node_modules/.bin/qunit -t path/test.js -c path/tests.js` 28 | 29 | ### References 30 | - [Data Structures and Algorithms with JavaScript](http://shop.oreilly.com/product/0636920029557.do) 31 | - [7 algorithms and data structures every programmer must know](https://codingsec.net/2016/03/7-algorithms-data-structures-every-programmer/) 32 | 33 | Some exercises are based from the book [Data Structures and Algorithms with JavaScript](http://shop.oreilly.com/product/0636920029557.do) - [by Michael McMillian (O’Reilly)](http://www.oreilly.com/pub/au/518) ISBN - 978-1-449-36493-9. 34 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | const {stack} = require('./04-chapter-Stack/') 3 | const {queue} = require('./05-chapter-Queue/') 4 | const {linked} = require('./06-chapter-Linked-Lists-types/') 5 | const {tree} = require('./10-chapter-Binary-Tree/') 6 | const {graph} = require('./11-chapter-Graphs/') 7 | const {sort} = require('./12-chapter-Sorting-Algorithms/') 8 | const {search} = require('./13-chapter-Searching-Algorithms/') 9 | 10 | Object.assign(exports, {stack, queue, linked, tree, graph, sort, search}) 11 | }((typeof module.exports !== undefined) ? module.exports : window)) 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data-structures-with-es6", 3 | "version": "1.0.0", 4 | "description": "Data Structures and Algorithims with ES6", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "qunit -t test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/Crizstian/data-structure-and-algorithms-with-ES6.git" 12 | }, 13 | "keywords": [ 14 | "Data", 15 | "Structures", 16 | "ES6", 17 | "Algorithms", 18 | "Prototypal", 19 | "Object", 20 | "Inheritance" 21 | ], 22 | "author": "Cristian Ramirez", 23 | "license": "ISC", 24 | "bugs": { 25 | "url": "https://github.com/Crizstian/data-structure-and-algorithms-with-ES6/issues" 26 | }, 27 | "homepage": "https://github.com/Crizstian/data-structure-and-algorithms-with-ES6#readme", 28 | "devDependencies": { 29 | "qunit": "^0.9.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crizstian/data-structure-and-algorithms-with-ES6/73c64c90aaf74d32d45061b639540bdcaf2e30d6/test.js --------------------------------------------------------------------------------