├── .gitignore ├── Dijkstra's Algorithm └── shortestPathGraph.js ├── Graph ├── directedGraph.js └── undirectedGraph.js ├── Hash Table └── hashTable.js ├── Heap ├── Binary Heap │ ├── maxBinaryHeap.js │ └── minBinaryHeap.js └── priorityQueue.js ├── LICENSE ├── Linked List ├── Circular Linked List │ ├── circularDoublyLinkedList.js │ └── circularSinglyLinkedList.js ├── Node │ ├── doublyNode.js │ └── singlyNode.js ├── Sorted Linked List │ ├── sortedDoublyLinkedList.js │ └── sortedSinglyLinkedList.js ├── doublyLinkedList.js └── singlyLinkedList.js ├── Queue ├── circularQueue.js ├── priorityQueue.js └── queue.js ├── README.md ├── Searching ├── binarySearch.js └── linearSearch.js ├── Sorting ├── Heap Sort │ ├── maxHeapSort.js │ └── minHeapSort.js ├── Quick Sort │ ├── quickSort (Normal Approach).js │ └── quickSort (Partition Approach).js ├── bubbleSort.js ├── insertionSort.js ├── mergeSort.js ├── radixSort.js └── selectionSort.js ├── Stack └── stack.js └── Tree ├── Binary Tree ├── binarySearchTree.js └── binaryTree.js ├── Node └── nodeTree.js └── basicTree.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /Dijkstra's Algorithm/shortestPathGraph.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(value, priority) 4 | { 5 | this.value = value; 6 | this.priority = priority; 7 | } 8 | } 9 | 10 | class PriorityQueue 11 | { 12 | constructor() 13 | { 14 | this.datas = []; 15 | this.count = 0; 16 | } 17 | 18 | enqueue(value, priority) // Time Complexity O(log n) 19 | { 20 | this.count++; 21 | 22 | let newNode = new Node(value, priority); 23 | 24 | this.datas.push(newNode); 25 | 26 | this.bubbleUp(); 27 | } 28 | 29 | bubbleUp() // Time Complexity O(log n) 30 | { 31 | let index = this.datas.length - 1; 32 | 33 | const elem = this.datas[index]; // 'data' will be stored in 'elem' 34 | 35 | while(index > 0) // Index must be greater than 0 36 | { 37 | let parentIndex = Math.floor((index - 1) / 2); // Parent Index 38 | let parent = this.datas[parentIndex]; // Parent index's data 39 | 40 | if(elem.priority >= parent.priority) break; 41 | // If the input 'data's priority is >= to data's priority in parent index, then we'll break out; 42 | 43 | // Otherwise we'll swap the values 44 | this.datas[parentIndex] = elem; // Will swap 'data' with parent index's data 45 | 46 | this.datas[index] = parent; // Then, new 'data' will be parent value 47 | 48 | index = parentIndex; // Update the index to parent index 49 | } 50 | } 51 | 52 | dequeue() // Time Complexity O(log n) 53 | { 54 | this.count--; 55 | let min = this.datas[0]; // Min data in Min ER 56 | 57 | let endData = this.datas.pop(); // Last data in Min ER 58 | 59 | let length = this.datas.length; 60 | if(length > 0) // if array length is greater than 0 61 | { 62 | this.datas[0] = endData; // The value of Min data is now 'endData' 63 | this.bubbleDown(); 64 | } 65 | return min; 66 | } 67 | 68 | bubbleDown() // Time Complexity O(log n) 69 | { 70 | let index = 0; 71 | 72 | const length = this.datas.length; 73 | 74 | const element = this.datas[0]; 75 | 76 | while(true) 77 | { 78 | let leftChildIndex = 2 * index + 1; 79 | let rightChildIndex = 2 * index + 2; 80 | 81 | let leftChild, rightChild; 82 | 83 | let swap = null; // It's going to keep track of the position, we'er going to swap with 84 | 85 | if(leftChildIndex < length) // leftChildIndex is inbound, then assign the value to the left child 86 | { 87 | leftChild = this.datas[leftChildIndex]; 88 | 89 | if(leftChild.priority < element.priority) // If leftChild is lesser than element then set swap equal to leftChildIndex 90 | { 91 | swap = leftChildIndex; 92 | } 93 | } 94 | 95 | if(rightChildIndex < length) // rightChildIndex is inbound, then assign the value to the right child 96 | { 97 | rightChild = this.datas[rightChildIndex]; 98 | 99 | if 100 | ( 101 | (swap === null && rightChild.priority < element.priority) || // If swap is still null & rightChild is lesser than element 102 | (swap !== null && rightChild.priority < leftChild.priority) // If swap isn't null & rightChild is lesser than leftChild 103 | ) 104 | { 105 | swap = rightChildIndex; // then set swap equal to rightChildIndex 106 | } 107 | } 108 | 109 | if(swap === null) break; 110 | 111 | // Otherwise we'll swap the values 112 | this.datas[index] = this.datas[swap]; // Will swap the data in 'swap's' index with parent data's index 113 | 114 | this.datas[swap] = element; // Then, new 'data' will be parent value 115 | 116 | index = swap; // Update the index to parent index 117 | } 118 | } 119 | } 120 | 121 | class ShortestPathGraph 122 | { 123 | constructor() 124 | { 125 | this.adjacencyList = {}; 126 | } 127 | 128 | addVertex(vertex) // Time Complexity O(1) 129 | { 130 | if(!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; // If the vertex doesn't exist, then add it. 131 | } 132 | 133 | removeVertex(vertex) // Time Complexity O(|VERTEX| + |EDGE|) 134 | { 135 | if(this.adjacencyList[vertex]) 136 | { 137 | while(this.adjacencyList[vertex].length) 138 | { 139 | this.adjacencyList[vertex].pop(); // Will pop all the value 140 | 141 | for (let key of Object.keys(this.adjacencyList)) // Will loop through all keys 142 | { 143 | if(this.adjacencyList[key].filter(value => value !== vertex)) 144 | { 145 | this.removeEdge(key, vertex); // Will remove all edges 146 | } 147 | } 148 | } 149 | delete this.adjacencyList[vertex]; 150 | } 151 | else throw new Error(`Vertex doesn't exist`); 152 | } 153 | 154 | addEdge(vertexOne, vertexTwo, weight) // Time Complexity O(1) 155 | { 156 | if(this.adjacencyList[vertexOne] && this.adjacencyList[vertexTwo]) // If both vertices exist 157 | { 158 | this.adjacencyList[vertexOne].push({Node: vertexTwo, Value: weight}); 159 | this.adjacencyList[vertexTwo].push({Node: vertexOne, Value: weight}); 160 | } 161 | else throw new Error(`Vertex doesn't exist`); 162 | } 163 | 164 | removeEdge(vertexOne, vertexTwo) // Time Complexity O(|EDGE|) 165 | { 166 | if(this.adjacencyList[vertexOne] && this.adjacencyList[vertexTwo]) // If both vertices exist 167 | { 168 | this.adjacencyList[vertexOne] = this.adjacencyList[vertexOne].filter(vertex => vertex.Node !== vertexTwo); 169 | this.adjacencyList[vertexTwo] = this.adjacencyList[vertexTwo].filter(vertex => vertex.Node !== vertexOne ); 170 | } 171 | else throw new Error(`Vertex doesn't exist`); 172 | } 173 | 174 | printGraph() 175 | { 176 | console.log('Graph:\n', this.adjacencyList); 177 | } 178 | 179 | dijkstra(startVertex, finishVertex) 180 | { 181 | const nodes = new PriorityQueue() 182 | const distances = {}; 183 | const previous = {}; 184 | let smallest; 185 | let path = []; 186 | 187 | // Building up initial state 188 | for (let vertex in this.adjacencyList) // Loop through all vertices 189 | { 190 | if (vertex === startVertex) 191 | { 192 | distances[vertex] = 0; 193 | nodes.enqueue(vertex, 0); 194 | } 195 | else 196 | { 197 | distances[vertex] = Infinity; 198 | nodes.enqueue(vertex, Infinity); 199 | } 200 | 201 | previous[vertex] = null; 202 | } 203 | 204 | let nodesLength = nodes.datas.length; 205 | 206 | while(nodesLength) // As long as there is something to visit 207 | { 208 | smallest = nodes.dequeue().value; 209 | 210 | if(smallest === finishVertex) 211 | { 212 | while(previous[smallest]) // Building up the Path 213 | { 214 | path.push(smallest); 215 | smallest = previous[smallest]; 216 | } 217 | break; 218 | } 219 | 220 | if(smallest || distances[smallest] !== Infinity) 221 | { 222 | for (let neighbor in this.adjacencyList[smallest]) 223 | { 224 | let nextNode = this.adjacencyList[smallest][neighbor]; // Finds neighboring node 225 | 226 | // Calculate new distance to neighboring node 227 | 228 | let newDistance = distances[smallest] + nextNode.Value; // Current smallest value + next node's Value 229 | 230 | let nextNeighbor = nextNode.Node; 231 | 232 | if(newDistance < distances[nextNeighbor]) 233 | { 234 | distances[nextNeighbor] = newDistance; // Updating new smallest distance to neighbor 235 | previous[nextNeighbor] = smallest; // Updating previous - how we got to neighbor 236 | nodes.enqueue(nextNeighbor, newDistance); // Equeue in PQ with new priority 237 | } 238 | } 239 | } 240 | } 241 | let result = path.concat(smallest).reverse().toString().replace(/,/g, ' -> '); 242 | 243 | console.log(`Shortest Path: ${result}`); 244 | 245 | return result; 246 | } 247 | } 248 | 249 | 250 | // This is an WEIGHTED UNDIRECTED GRAPH 251 | 252 | /* 253 | 254 | Dhaka 255 | 1500 / \ 1200 256 | / 1300 \ 257 | Tokyo------Istanbul 258 | | | 259 | 1400 | | 1000 260 | | 500 | 261 | London------Berlin 262 | \ / 263 | 600 \ / 800 264 | NYC 265 | 266 | */ 267 | 268 | 269 | let graph = new ShortestPathGraph(); 270 | 271 | graph.addVertex("Tokyo"); 272 | graph.addVertex("Dhaka"); 273 | graph.addVertex("Istanbul"); 274 | graph.addVertex("London"); 275 | graph.addVertex("Berlin"); 276 | graph.addVertex("NYC"); 277 | 278 | graph.addEdge("Dhaka", "Tokyo", 1500); 279 | graph.addEdge("Dhaka", "Istanbul", 1200); 280 | graph.addEdge("Tokyo","London", 1400); 281 | graph.addEdge("Berlin", "Istanbul", 1000); 282 | graph.addEdge("London", "Berlin", 500); 283 | graph.addEdge("London", "NYC", 600); 284 | graph.addEdge("NYC", "Berlin", 800); 285 | graph.addEdge("Istanbul", "Tokyo", 1300); 286 | 287 | graph.printGraph(); 288 | graph.dijkstra("Dhaka", "NYC"); 289 | 290 | 291 | graph.removeEdge("Dhaka", "Istanbul", 1200); 292 | 293 | /* 294 | 295 | Dhaka 296 | 1500 / 297 | / 1300 298 | Tokyo------Istanbul 299 | | | 300 | 1400 | | 1000 301 | | 500 | 302 | London------Berlin 303 | \ / 304 | 600 \ / 800 305 | NYC 306 | 307 | */ 308 | 309 | graph.printGraph(); 310 | graph.dijkstra("Berlin", "Dhaka"); 311 | 312 | 313 | graph.removeVertex("Berlin"); 314 | graph.addEdge("Istanbul", "NYC", 600); 315 | 316 | /* 317 | 318 | Dhaka 319 | 1500 / 320 | / 1300 321 | Tokyo------Istanbul 322 | | | 323 | 1400 | | 324 | | | 325 | London | 600 326 | \ / 327 | 600 \ / 328 | NYC 329 | 330 | */ 331 | 332 | graph.printGraph(); 333 | graph.dijkstra("NYC", "Dhaka"); 334 | -------------------------------------------------------------------------------- /Graph/directedGraph.js: -------------------------------------------------------------------------------- 1 | class DirectedGraph 2 | { 3 | constructor() 4 | { 5 | this.adjacencyList = {}; 6 | } 7 | 8 | addVertex(vertex) // Time Complexity O(1) 9 | { 10 | if(!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; // If the vertex doesn't exist, then add it. 11 | } 12 | 13 | removeVertex(vertex) // Time Complexity O(|VERTEX| + |EDGE|) 14 | { 15 | if(this.adjacencyList[vertex]) 16 | { 17 | while(this.adjacencyList[vertex].length) 18 | { 19 | this.adjacencyList[vertex].pop(); // Will pop all the value 20 | 21 | for (let key of Object.keys(this.adjacencyList)) // Will loop through all keys 22 | { 23 | if(this.adjacencyList[key].filter(value => value !== vertex)) 24 | { 25 | this.removeEdge(key, vertex); // Will remove all edges 26 | } 27 | } 28 | } 29 | delete this.adjacencyList[vertex]; 30 | } 31 | else throw new Error(`Vertex doesn't exist`); 32 | } 33 | 34 | addEdge(vertexOne, vertexTwo) // Time Complexity O(1) 35 | { 36 | if(this.adjacencyList[vertexOne] && this.adjacencyList[vertexTwo]) // If both vertices exist 37 | { 38 | this.adjacencyList[vertexOne].push(vertexTwo); 39 | } 40 | else throw new Error(`Vertex doesn't exist`); 41 | } 42 | 43 | removeEdge(vertexOne, vertexTwo) // Time Complexity O(|EDGE|) 44 | { 45 | if(this.adjacencyList[vertexOne] && this.adjacencyList[vertexTwo]) // If both vertices exist 46 | { 47 | this.adjacencyList[vertexOne] = this.adjacencyList[vertexOne].filter(vertex => vertex !== vertexTwo); 48 | } 49 | else throw new Error(`Vertex doesn't exist`); 50 | } 51 | 52 | printGraph() 53 | { 54 | console.log('Graph:\n', this.adjacencyList); 55 | } 56 | 57 | // Recursive DFS 58 | 59 | DFS(startVertex) 60 | { 61 | let result = []; 62 | let visited = {}; 63 | let adjacencyList = this.adjacencyList; 64 | 65 | (function DFSRecursive(vertex) 66 | { 67 | if(!vertex) return null; // If the vertex doesn't exist, return null 68 | 69 | visited[vertex] = true; // Will set the vertex as visited 70 | 71 | result.push(vertex); // Then push the vertex 72 | 73 | adjacencyList[vertex].forEach(neighbor => // Will loop through all the vertices 74 | { 75 | if(!visited[neighbor]) return DFSRecursive(neighbor); // If the vertex is not visited, we'll do recursion 76 | }); 77 | })(startVertex); 78 | 79 | console.log(`DFS: ${result}`); 80 | 81 | return result; 82 | } 83 | 84 | 85 | // Iterative DFS 86 | /* 87 | DFS(startVertex) 88 | { 89 | let stack = [startVertex]; // Will keep track of vertices 90 | let result = []; 91 | let visited = {}; 92 | let currentVertex; 93 | 94 | visited[startVertex] = true; // Will set the vertex as visited 95 | 96 | while(stack.length) // while stack is not empty 97 | { 98 | currentVertex = stack.pop(); // Pop, then 99 | 100 | result.push(currentVertex); // push to the result array 101 | 102 | this.adjacencyList[currentVertex].forEach(neighbor => // Will loop through all the vertices 103 | { 104 | if(!visited[neighbor]) // If the vertex is not visited 105 | { 106 | visited[neighbor] = true; // make it visited 107 | 108 | stack.push(neighbor); // Then push it to the stack 109 | } 110 | }); 111 | } 112 | 113 | console.log(`DFS: ${result}`); 114 | 115 | return result; 116 | } 117 | */ 118 | 119 | BFS(startVertex) 120 | { 121 | let queue = [startVertex]; // Will keep track of vertices 122 | let result = []; 123 | let visited = {}; 124 | let currentVertex; 125 | 126 | visited[startVertex] = true; // Will set the vertex as visited 127 | 128 | while(queue.length) // while stack is not empty 129 | { 130 | currentVertex = queue.shift(); // Shift, then 131 | 132 | result.push(currentVertex); // push to the result array 133 | 134 | this.adjacencyList[currentVertex].slice().reverse().forEach(neighbor => // Will loop through all the vertices 135 | { 136 | if(!visited[neighbor]) // If the vertex is not visited 137 | { 138 | visited[neighbor] = true; // make it visited 139 | 140 | queue.push(neighbor); // Then push it to the queue 141 | } 142 | }); 143 | } 144 | 145 | console.log(`BFS: ${result}`); 146 | 147 | return result; 148 | } 149 | } 150 | 151 | // There will be a difference between the output of Recursive DFS & Iterative DFS 152 | 153 | // To change the order of BFS do 'this.adjacencyList[currentVertex].slice().reverse().forEach' on line 134 154 | 155 | // This is an UNWEIGHTED DIRECTED GRAPH 156 | 157 | /* 158 | 159 | Dhaka 160 | / \ 161 | \/ \/ 162 | Tokyo Istanbul 163 | | | 164 | | | 165 | \|/ \|/ 166 | London <--- Berlin 167 | /\ /\ 168 | \ / 169 | NYC 170 | 171 | */ 172 | 173 | 174 | let graph = new DirectedGraph(); 175 | 176 | graph.addVertex("Tokyo"); 177 | graph.addVertex("Dhaka"); 178 | graph.addVertex("Istanbul"); 179 | graph.addVertex("London"); 180 | graph.addVertex("Berlin"); 181 | graph.addVertex("NYC"); 182 | 183 | graph.addEdge("Dhaka", "Tokyo"); 184 | graph.addEdge("Dhaka", "Istanbul"); 185 | graph.addEdge("Tokyo","London"); 186 | graph.addEdge("Istanbul", "Berlin"); 187 | graph.addEdge("NYC", "London"); 188 | graph.addEdge("Berlin", "London"); 189 | graph.addEdge("NYC", "Berlin"); 190 | 191 | graph.printGraph(); 192 | graph.DFS("Dhaka"); 193 | graph.BFS("Dhaka"); 194 | 195 | 196 | graph.removeEdge("Dhaka", "Istanbul") 197 | 198 | /* 199 | 200 | Dhaka 201 | / 202 | \/ 203 | Tokyo Istanbul 204 | | | 205 | | | 206 | \|/ \|/ 207 | London <--- Berlin 208 | /\ /\ 209 | \ / 210 | NYC 211 | 212 | */ 213 | 214 | graph.printGraph(); 215 | graph.DFS("Dhaka"); 216 | graph.BFS("NYC"); 217 | 218 | graph.removeVertex("Berlin"); 219 | 220 | /* 221 | 222 | Dhaka 223 | / 224 | \/ 225 | Tokyo Istanbul 226 | | | 227 | | | 228 | \|/ \|/ 229 | London <---- 230 | /\ /\ 231 | \ / 232 | NYC 233 | 234 | */ 235 | 236 | graph.printGraph(); 237 | graph.DFS("NYC"); 238 | graph.BFS("Dhaka"); 239 | -------------------------------------------------------------------------------- /Graph/undirectedGraph.js: -------------------------------------------------------------------------------- 1 | class UndirectedGraph 2 | { 3 | constructor() 4 | { 5 | this.adjacencyList = {}; 6 | } 7 | 8 | addVertex(vertex) // Time Complexity O(1) 9 | { 10 | if(!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; // If the vertex doesn't exist, then add it. 11 | } 12 | 13 | removeVertex(vertex) // Time Complexity O(|VERTEX| + |EDGE|) 14 | { 15 | if(this.adjacencyList[vertex]) 16 | { 17 | while(this.adjacencyList[vertex].length) 18 | { 19 | let adjacentVertex = this.adjacencyList[vertex].pop(); // Will pop all the value 20 | this.removeEdge(vertex, adjacentVertex); // Will remove all edges 21 | } 22 | delete this.adjacencyList[vertex]; 23 | } 24 | else throw new Error(`Vertex doesn't exist`); 25 | } 26 | 27 | addEdge(vertexOne, vertexTwo) // Time Complexity O(1) 28 | { 29 | if(this.adjacencyList[vertexOne] && this.adjacencyList[vertexTwo]) // If both vertices exist 30 | { 31 | this.adjacencyList[vertexOne].push(vertexTwo); 32 | this.adjacencyList[vertexTwo].push(vertexOne); 33 | } 34 | else throw new Error(`Vertex doesn't exist`); 35 | } 36 | 37 | removeEdge(vertexOne, vertexTwo) // Time Complexity O(|EDGE|) 38 | { 39 | if(this.adjacencyList[vertexOne] && this.adjacencyList[vertexTwo]) // If both vertices exist 40 | { 41 | this.adjacencyList[vertexOne] = this.adjacencyList[vertexOne].filter(vertex => vertex !== vertexTwo); 42 | this.adjacencyList[vertexTwo] = this.adjacencyList[vertexTwo].filter(vertex => vertex !== vertexOne); 43 | } 44 | else throw new Error(`Vertex doesn't exist`); 45 | } 46 | 47 | printGraph() 48 | { 49 | console.log('Graph:\n', this.adjacencyList); 50 | } 51 | 52 | // Recursive DFS 53 | 54 | DFS(startVertex) 55 | { 56 | let result = []; 57 | let visited = {}; 58 | let adjacencyList = this.adjacencyList; 59 | 60 | (function DFSRecursive(vertex) 61 | { 62 | if(!vertex) return null; // If the vertex doesn't exist, return null 63 | 64 | visited[vertex] = true; // Will set the vertex as visited 65 | 66 | result.push(vertex); // Then push the vertex 67 | 68 | adjacencyList[vertex].forEach(neighbor => // Will loop through all the vertices 69 | { 70 | if(!visited[neighbor]) return DFSRecursive(neighbor); // If the vertex is not visited, we'll do recursion 71 | }); 72 | })(startVertex); 73 | 74 | console.log(`DFS: ${result}`); 75 | 76 | return result; 77 | } 78 | 79 | 80 | // Iterative DFS 81 | /* 82 | DFS(startVertex) 83 | { 84 | let stack = [startVertex]; // Will keep track of vertices 85 | let result = []; 86 | let visited = {}; 87 | let currentVertex; 88 | 89 | visited[startVertex] = true; // Will set the vertex as visited 90 | 91 | while(stack.length) // while stack is not empty 92 | { 93 | currentVertex = stack.pop(); // Pop, then 94 | 95 | result.push(currentVertex); // push to the result array 96 | 97 | this.adjacencyList[currentVertex].forEach(neighbor => // Will loop through all the vertices 98 | { 99 | if(!visited[neighbor]) // If the vertex is not visited 100 | { 101 | visited[neighbor] = true; // make it visited 102 | 103 | stack.push(neighbor); // Then push it to the stack 104 | } 105 | }); 106 | } 107 | 108 | console.log(`DFS: ${result}`); 109 | 110 | return result; 111 | } 112 | */ 113 | 114 | BFS(startVertex) 115 | { 116 | let queue = [startVertex]; // Will keep track of vertices 117 | let result = []; 118 | let visited = {}; 119 | let currentVertex; 120 | 121 | visited[startVertex] = true; // Will set the vertex as visited 122 | 123 | while(queue.length) // while stack is not empty 124 | { 125 | currentVertex = queue.shift(); // Shift, then 126 | 127 | result.push(currentVertex); // push to the result array 128 | 129 | this.adjacencyList[currentVertex].forEach(neighbor => // Will loop through all the vertices 130 | { 131 | if(!visited[neighbor]) // If the vertex is not visited 132 | { 133 | visited[neighbor] = true; // make it visited 134 | 135 | queue.push(neighbor); // Then push it to the queue 136 | } 137 | }); 138 | } 139 | 140 | console.log(`BFS: ${result}`); 141 | 142 | return result; 143 | } 144 | } 145 | 146 | // There will be a difference between the output of Recursive DFS & Iterative DFS 147 | 148 | // To change the order of BFS do 'this.adjacencyList[currentVertex].slice().reverse().forEach' on line 131 149 | 150 | // This is an UNWEIGHTED UNDIRECTED GRAPH 151 | 152 | /* 153 | 154 | Dhaka 155 | / \ 156 | / \ 157 | Tokyo Istanbul 158 | | | 159 | | | 160 | | | 161 | London------Berlin 162 | \ / 163 | \ / 164 | NYC 165 | 166 | */ 167 | 168 | 169 | let graph = new UndirectedGraph(); 170 | 171 | graph.addVertex("Tokyo"); 172 | graph.addVertex("Dhaka"); 173 | graph.addVertex("Istanbul"); 174 | graph.addVertex("London"); 175 | graph.addVertex("Berlin"); 176 | graph.addVertex("NYC"); 177 | 178 | graph.addEdge("Dhaka", "Tokyo"); 179 | graph.addEdge("Dhaka", "Istanbul"); 180 | graph.addEdge("Tokyo","London"); 181 | graph.addEdge("Berlin", "Istanbul"); 182 | graph.addEdge("London", "Berlin"); 183 | graph.addEdge("London", "NYC"); 184 | graph.addEdge("NYC", "Berlin"); 185 | 186 | graph.printGraph(); 187 | graph.DFS("Dhaka"); 188 | graph.BFS("Dhaka"); 189 | 190 | 191 | graph.removeEdge("Dhaka", "Istanbul") 192 | 193 | /* 194 | 195 | Dhaka 196 | / 197 | / 198 | Tokyo Istanbul 199 | | | 200 | | | 201 | | | 202 | London------Berlin 203 | \ / 204 | \ / 205 | NYC 206 | 207 | */ 208 | 209 | graph.printGraph(); 210 | graph.DFS("Dhaka"); 211 | graph.BFS("Dhaka"); 212 | 213 | graph.removeVertex("Berlin"); 214 | 215 | /* 216 | 217 | Dhaka 218 | / 219 | / 220 | Tokyo Istanbul 221 | | | 222 | | | 223 | | | 224 | London------ 225 | \ / 226 | \ / 227 | NYC 228 | 229 | */ 230 | 231 | graph.printGraph(); 232 | graph.DFS("Dhaka"); 233 | graph.BFS("Dhaka"); 234 | -------------------------------------------------------------------------------- /Hash Table/hashTable.js: -------------------------------------------------------------------------------- 1 | class HashTable 2 | { 3 | constructor(size) 4 | { 5 | this.keyMap = new Array(size); 6 | } 7 | 8 | hash(key) // Time Complexity O(n) 9 | { 10 | let hashedKey = 0; 11 | 12 | for (let i = 0; i < key.length; i++) 13 | { 14 | hashedKey += key.charCodeAt(i) - 96; // UTF-16 value of ith character of key - 96 15 | } 16 | 17 | return hashedKey % this.keyMap.length; 18 | } 19 | 20 | set(key, value) // Time Complexity O(n) 21 | { 22 | // Separate Chaining approach 23 | 24 | let index = this.hash(key); 25 | 26 | if(!this.keyMap[index]) this.keyMap[index] = []; // If the index is empty, set it as an empty array 27 | 28 | this.keyMap[index].push([key,value]); // Push the value 29 | } 30 | 31 | get(key) // Time Complexity O(n) 32 | { 33 | let index = this.hash(key); 34 | 35 | if(this.keyMap[index]) // Index isn't empty 36 | { 37 | for(let i = 0; i < this.keyMap[index].length; i++) 38 | { 39 | if(this.keyMap[index][i][0] === key) // If value of key is found 40 | { 41 | let key = this.keyMap[index][i][0]; 42 | let value = this.keyMap[index][i][1]; 43 | 44 | console.log(`Key: ${key}, Value: ${value}`); 45 | } 46 | } 47 | } 48 | return undefined; 49 | } 50 | 51 | values() // Time Complexity O(n^2) 52 | { 53 | let valuesArr = []; 54 | 55 | for (let i = 0; i < this.keyMap.length; i++) 56 | { 57 | if (this.keyMap[i]) // If there is data in ith index 58 | { 59 | for (let j = 0; j < this.keyMap[i].length; j++) // Will loop through total number of data 60 | { 61 | if(!valuesArr.includes(this.keyMap[i][j][1])) // Checking for duplicates 62 | { 63 | valuesArr.push(this.keyMap[i][j][1]); 64 | } 65 | } 66 | } 67 | 68 | } 69 | 70 | console.log(`Values: ${valuesArr.join(', ')}`); 71 | } 72 | 73 | keys() // Time Complexity O(n^2) 74 | { 75 | let keysArr = []; 76 | 77 | for (let i = 0; i < this.keyMap.length; i++) 78 | { 79 | if (this.keyMap[i]) // If there is data in ith index 80 | { 81 | for (let j = 0; j < this.keyMap[i].length; j++) // Will loop through total number of data 82 | { 83 | if(!keysArr.includes(this.keyMap[i][j][0])) // Checking for duplicates 84 | { 85 | keysArr.push(this.keyMap[i][j][0]); 86 | } 87 | } 88 | } 89 | 90 | } 91 | 92 | console.log(`Keys: ${keysArr.join(', ')}`); 93 | } 94 | 95 | remove(key) // Time Complexity O(n) 96 | { 97 | let index = this.hash(key); 98 | 99 | let flag = false; 100 | if(this.keyMap[index]) // Index isn't empty 101 | { 102 | for(let i = 0; i < this.keyMap[index].length; i++) 103 | { 104 | if(this.keyMap[index][i][0] === key) // If value of key is found 105 | { 106 | console.log(`Key: ${key} is deleted`); 107 | delete this.keyMap[index][i]; 108 | 109 | flag = true; 110 | } 111 | } 112 | } 113 | if(!flag) console.log(`Key: ${key} is not found`); 114 | } 115 | 116 | print() 117 | { 118 | console.log(this.keyMap); 119 | } 120 | } 121 | 122 | // Space Complexity O(n) 123 | // This isn't a efficient version 124 | // This hash table is only useful for strings 125 | // To set value "Separate Chaining" approach is used 126 | 127 | /* 128 | let ht = new HashTable(23); 129 | 130 | ht.set("tomato", "#FF6347"); 131 | ht.set("yellow", "#FFFF00"); 132 | ht.set("red", "#FF0000"); 133 | ht.set("salmon", "#FA8072"); 134 | ht.set("lime", "#00FF00"); 135 | ht.set("pink", "#FFC0CB"); 136 | ht.set("orchid", "#DA70D6"); 137 | ht.set("violet", "#EE82EE"); 138 | ht.set("purple", "#800080"); 139 | ht.set("purple", "#DA70D6"); 140 | ht.set("purple", "#DA70D6"); 141 | 142 | ht.print(); 143 | 144 | ht.get("red"); 145 | 146 | ht.keys(); 147 | 148 | ht.values(); 149 | 150 | 151 | ht.remove(453); 152 | ht.remove('red'); 153 | 154 | ht.print(); 155 | */ -------------------------------------------------------------------------------- /Heap/Binary Heap/maxBinaryHeap.js: -------------------------------------------------------------------------------- 1 | class MaxBinaryHeap 2 | { 3 | constructor() 4 | { 5 | this.datas = []; 6 | this.count = 0; 7 | } 8 | 9 | insert(data) // Time Complexity O(log n) 10 | { 11 | this.count++; 12 | this.datas.push(data); 13 | 14 | this.bubbleUp(); 15 | } 16 | 17 | bubbleUp() // Time Complexity O(log n) 18 | { 19 | let index = this.datas.length - 1; 20 | 21 | const elem = this.datas[index]; // 'data' will be stored in 'elem' 22 | 23 | while(index > 0) // Index must be greater than 0 24 | { 25 | let parentIndex = Math.floor((index - 1) / 2); // Parent Index 26 | let parent = this.datas[parentIndex]; // Parent index's data 27 | 28 | if(elem <= parent) break; 29 | // If the input 'data' is <= to parent index's data, then we'll break out; 30 | 31 | // Otherwise we'll swap the values 32 | this.datas[parentIndex] = elem; // Will swap 'data' with parent index's data 33 | 34 | this.datas[index] = parent; // Then, new 'data' will be parent value 35 | 36 | index = parentIndex; // Update the index to parent index 37 | } 38 | } 39 | 40 | extractMax() // Time Complexity O(log n) 41 | { 42 | this.count--; 43 | let max = this.datas[0]; // Max data in Max Heap 44 | 45 | let endData = this.datas.pop(); // Last data in Max Heap 46 | 47 | let length = this.datas.length; 48 | if(length > 0) // if array length is greater than 0 49 | { 50 | this.datas[0] = endData; // The value of Max data is now 'endData' 51 | this.bubbleDown(); 52 | } 53 | 54 | console.log(`${max} removed from Max Binary Heap`); 55 | 56 | return max; 57 | } 58 | 59 | bubbleDown() // Time Complexity O(log n) 60 | { 61 | let index = 0; 62 | 63 | const length = this.datas.length; 64 | 65 | const element = this.datas[0]; 66 | 67 | while(true) 68 | { 69 | let leftChildIndex = 2 * index + 1; 70 | let rightChildIndex = 2 * index + 2; 71 | 72 | let leftChild, rightChild; 73 | 74 | let swap = null; // It's going to keep track of the position, we'er going to swap with 75 | 76 | if(leftChildIndex < length) // leftChildIndex is inbound, then assign the value to the left child 77 | { 78 | leftChild = this.datas[leftChildIndex]; 79 | 80 | if(leftChild > element) // If leftChild is greater than element then set swap equal to leftChildIndex 81 | { 82 | swap = leftChildIndex; 83 | } 84 | } 85 | 86 | if(rightChildIndex < length) // rightChildIndex is inbound, then assign the value to the right child 87 | { 88 | rightChild = this.datas[rightChildIndex]; 89 | 90 | if 91 | ( 92 | (swap === null && rightChild > element) || // If swap is still null & rightChild is greater than element 93 | (swap !== null && rightChild > leftChild) // If swap isn't null & rightChild is greater than leftChild 94 | ) 95 | { 96 | swap = rightChildIndex; // then set swap equal to rightChildIndex 97 | } 98 | } 99 | 100 | if(swap === null) break; 101 | 102 | // Otherwise we'll swap the values 103 | this.datas[index] = this.datas[swap]; // Will swap the data in 'swap's' index with parent data's index 104 | 105 | this.datas[swap] = element; // Then, new 'data' will be parent value 106 | 107 | index = swap; // Update the index to parent index 108 | } 109 | } 110 | 111 | print() 112 | { 113 | console.log(`Max Binary Heap : ${this.datas.join(' ')}`); 114 | } 115 | 116 | size() 117 | { 118 | console.log(`Total datas in Max Binary Heap: ${this.count}`); 119 | } 120 | 121 | findLeftChild(data) 122 | { 123 | let index = this.datas.indexOf(data); 124 | 125 | let leftChild = this.datas[2 * index + 1]; 126 | 127 | if(leftChild) console.log(`Left Child of ${data} is ${leftChild}`); 128 | else console.log(`No left child of '${data}' found`); 129 | } 130 | 131 | findRightChild(data) 132 | { 133 | let index = this.datas.indexOf(data); 134 | 135 | let rightChild = this.datas[2 * index + 2]; 136 | 137 | if(rightChild) console.log(`Right Child of ${data} is ${rightChild}`); 138 | else console.log(`No right child of '${data}' found`); 139 | } 140 | 141 | 142 | findParent(data) 143 | { 144 | let index = this.datas.indexOf(data); 145 | 146 | let parent = this.datas[Math.floor((index - 1) / 2)]; 147 | 148 | if(parent) console.log(`Parent of ${data} is ${parent}`); 149 | else console.log(`'${data}' is the root`); 150 | } 151 | 152 | maxHeapify(arr, len, index) // Time Complexity O(log n) 153 | { 154 | let max = index; // Parent Index 155 | let leftIndex = 2 * index + 1; // Left Index 156 | let rightIndex = 2 * index + 2; // Right Index 157 | 158 | if(leftIndex < len && arr[leftIndex] > arr[max]) // If left child of parent exists and is greater than max 159 | { 160 | max = leftIndex; 161 | } 162 | 163 | if(rightIndex < len && arr[rightIndex] > arr[max]) // If right child of parent exists and is greater than max 164 | { 165 | max = rightIndex; 166 | } 167 | 168 | if(max !== index) // If max is not parent index 169 | { 170 | [arr[index], arr[max]] = [arr[max], arr[index]]; // Swap values 171 | 172 | this.maxHeapify(arr, len, max); 173 | } 174 | 175 | return arr; 176 | } 177 | 178 | maxHeapSort() // Time Complexity O(n log n) 179 | { 180 | let arr = this.datas; 181 | let length = arr.length; 182 | 183 | let lastParent = Math.floor(length / 2 - 1); 184 | let lastChild = length - 1; 185 | 186 | for(let i = lastParent; i >= 0; i--) 187 | { 188 | this.maxHeapify(arr, length, lastParent); // Building max heap 189 | } 190 | 191 | for(let i = lastChild; i > 0; i--) 192 | { 193 | [arr[0], arr[i]] = [arr[i], arr[0]]; // Swap parent with last node 194 | 195 | this.maxHeapify(arr, i, 0); // Again calling heapify on the reduced heap 196 | } 197 | 198 | console.log(`Sorted Max Heap: ${arr.join(' ')}`); 199 | return arr; 200 | } 201 | } 202 | 203 | // Space Complexity O(n) 204 | // Complete Binary Tree is required 205 | 206 | /* 207 | 100 208 | / \ 209 | 52 43 210 | / \ / \ 211 | 33 47 10 35 212 | ------------------| | 213 | / \ ---------| 214 | 1 16 / 215 | 22 216 | */ 217 | // Before starting extraction 218 | 219 | /* 220 | let heap = new MaxBinaryHeap(); 221 | 222 | heap.insert(43); 223 | heap.insert(33); 224 | heap.insert(35); 225 | heap.insert(16); 226 | heap.insert(22); 227 | heap.insert(10); 228 | heap.insert(52); 229 | heap.insert(1); 230 | heap.insert(47); 231 | heap.insert(100); 232 | 233 | heap.print(); 234 | 235 | heap.findLeftChild(1); 236 | heap.findRightChild(43); 237 | heap.findParent(22); 238 | heap.findParent(100); 239 | 240 | heap.size() 241 | 242 | heap.extractMax(); 243 | 244 | heap.print(); 245 | 246 | heap.size(); 247 | 248 | heap.maxHeapSort(); 249 | */ -------------------------------------------------------------------------------- /Heap/Binary Heap/minBinaryHeap.js: -------------------------------------------------------------------------------- 1 | class MinBinaryHeap 2 | { 3 | constructor() 4 | { 5 | this.datas = []; 6 | this.count = 0; 7 | } 8 | 9 | insert(data) // Time Complexity O(log n) 10 | { 11 | this.count++; 12 | this.datas.push(data); 13 | 14 | this.bubbleUp(); 15 | } 16 | 17 | bubbleUp() // Time Complexity O(log n) 18 | { 19 | let index = this.datas.length - 1; 20 | 21 | const elem = this.datas[index]; // 'data' will be stored in 'elem' 22 | 23 | while(index > 0) // Index must be greater than 0 24 | { 25 | let parentIndex = Math.floor((index - 1) / 2); // Parent Index 26 | let parent = this.datas[parentIndex]; // Parent index's data 27 | 28 | if(elem >= parent) break; 29 | // If the input 'data' is >= to parent index's data, then we'll break out; 30 | 31 | // Otherwise we'll swap the values 32 | this.datas[parentIndex] = elem; // Will swap 'data' with parent index's data 33 | 34 | this.datas[index] = parent; // Then, new 'data' will be parent value 35 | 36 | index = parentIndex; // Update the index to parent index 37 | } 38 | } 39 | 40 | extractMin() // Time Complexity O(log n) 41 | { 42 | this.count--; 43 | let min = this.datas[0]; // Min data in Min Heap 44 | 45 | let endData = this.datas.pop(); // Last data in Min Heap 46 | 47 | let length = this.datas.length; 48 | if(length > 0) // if array length is greater than 0 49 | { 50 | this.datas[0] = endData; // The value of Min data is now 'endData' 51 | this.bubbleDown(); 52 | } 53 | 54 | console.log(`${min} removed from Min Binary Heap`); 55 | 56 | return min; 57 | } 58 | 59 | bubbleDown() // Time Complexity O(log n) 60 | { 61 | let index = 0; 62 | 63 | const length = this.datas.length; 64 | 65 | const element = this.datas[0]; 66 | 67 | while(true) 68 | { 69 | let leftChildIndex = 2 * index + 1; 70 | let rightChildIndex = 2 * index + 2; 71 | 72 | let leftChild, rightChild; 73 | 74 | let swap = null; // It's going to keep track of the position, we'er going to swap with 75 | 76 | if(leftChildIndex < length) // leftChildIndex is inbound, then assign the value to the left child 77 | { 78 | leftChild = this.datas[leftChildIndex]; 79 | 80 | if(leftChild < element) // If leftChild is lesser than element then set swap equal to leftChildIndex 81 | { 82 | swap = leftChildIndex; 83 | } 84 | } 85 | 86 | if(rightChildIndex < length) // rightChildIndex is inbound, then assign the value to the right child 87 | { 88 | rightChild = this.datas[rightChildIndex]; 89 | 90 | if 91 | ( 92 | (swap === null && rightChild < element) || // If swap is still null & rightChild is lesser than element 93 | (swap !== null && rightChild < leftChild) // If swap isn't null & rightChild is lesser than leftChild 94 | ) 95 | { 96 | swap = rightChildIndex; // then set swap equal to rightChildIndex 97 | } 98 | } 99 | 100 | if(swap === null) break; 101 | 102 | // Otherwise we'll swap the values 103 | this.datas[index] = this.datas[swap]; // Will swap the data in 'swap's' index with parent data's index 104 | 105 | this.datas[swap] = element; // Then, new 'data' will be parent value 106 | 107 | index = swap; // Update the index to parent index 108 | } 109 | } 110 | 111 | print() 112 | { 113 | console.log(`Min Binary Heap : ${this.datas.join(' ')}`); 114 | } 115 | 116 | size() 117 | { 118 | console.log(`Total datas in Min Binary Heap: ${this.count}`); 119 | } 120 | 121 | findLeftChild(data) 122 | { 123 | let index = this.datas.indexOf(data); 124 | 125 | let leftChild = this.datas[2 * index + 1]; 126 | 127 | if(leftChild) console.log(`Left Child of ${data} is ${leftChild}`); 128 | else console.log(`No left child of '${data}' found`); 129 | } 130 | 131 | findRightChild(data) 132 | { 133 | let index = this.datas.indexOf(data); 134 | 135 | let rightChild = this.datas[2 * index + 2]; 136 | 137 | if(rightChild) console.log(`Right Child of ${data} is ${rightChild}`); 138 | else console.log(`No right child of '${data}' found`); 139 | } 140 | 141 | 142 | findParent(data) 143 | { 144 | let index = this.datas.indexOf(data); 145 | 146 | let parent = this.datas[Math.floor((index - 1) / 2)]; 147 | 148 | if(parent) console.log(`Parent of ${data} is ${parent}`); 149 | else console.log(`'${data}' is the root`); 150 | } 151 | 152 | minHeapify(arr, len, index) // Time Complexity O(log n) 153 | { 154 | let min = index; // Parent Index 155 | let leftIndex = 2 * index + 1; // Left Index 156 | let rightIndex = 2 * index + 2; // Right Index 157 | 158 | if(leftIndex < len && arr[leftIndex] < arr[min]) // If left child of parent exists and is less than min 159 | { 160 | min = leftIndex; 161 | } 162 | 163 | if(rightIndex < len && arr[rightIndex] < arr[min]) // If right child of parent exists and is less than min 164 | { 165 | min = rightIndex; 166 | } 167 | 168 | if(min !== index) // If min is not parent index 169 | { 170 | [arr[index], arr[min]] = [arr[min], arr[index]]; // Swap values 171 | 172 | this.minHeapify(arr, len, min); 173 | } 174 | return arr; 175 | } 176 | 177 | minHeapSort() // Time Complexity O(n log n) 178 | { 179 | let arr = this.datas; 180 | let length = arr.length; 181 | 182 | let lastParent = Math.floor(length / 2 - 1); 183 | let lastChild = length - 1; 184 | 185 | for(let i = lastParent; i >= 0; i--) 186 | { 187 | this.minHeapify(arr, length, lastParent); // Building min heap 188 | } 189 | 190 | for(let i = lastChild; i > 0; i--) 191 | { 192 | [arr[0], arr[i]] = [arr[i], arr[0]]; // Swap parent with last node 193 | 194 | this.minHeapify(arr, i, 0); // Again calling minHeapify on the reduced heap 195 | } 196 | 197 | console.log(`Sorted Min Heap: ${arr.join(' ')}`); 198 | return arr; 199 | } 200 | } 201 | 202 | // Space Complexity O(n) 203 | // Complete Binary Tree is required 204 | 205 | /* 206 | 1 207 | / \ 208 | 10 16 209 | / \ / \ 210 | 22 33 35 52 211 | ------------------| | 212 | / \ ---------| 213 | 43 47 / 214 | 100 215 | */ 216 | // Before starting extraction 217 | 218 | /* 219 | let heap = new MinBinaryHeap(); 220 | 221 | heap.insert(43); 222 | heap.insert(33); 223 | heap.insert(35); 224 | heap.insert(16); 225 | heap.insert(22); 226 | heap.insert(10); 227 | heap.insert(52); 228 | heap.insert(1); 229 | heap.insert(47); 230 | heap.insert(100); 231 | 232 | heap.print(); 233 | 234 | heap.findLeftChild(16); 235 | heap.findRightChild(43); 236 | heap.findParent(1); 237 | heap.findParent(100); 238 | 239 | heap.size() 240 | 241 | heap.extractMin(); 242 | 243 | heap.print(); 244 | 245 | heap.size(); 246 | 247 | heap.minHeapSort(); 248 | */ -------------------------------------------------------------------------------- /Heap/priorityQueue.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(value, priority) 4 | { 5 | this.value = value; 6 | this.priority = priority; 7 | } 8 | } 9 | 10 | class PriorityQueue 11 | { 12 | constructor() 13 | { 14 | this.datas = []; 15 | this.count = 0; 16 | } 17 | 18 | enqueue(value, priority) // Time Complexity O(log n) 19 | { 20 | this.count++; 21 | 22 | let newNode = new Node(value, priority); 23 | 24 | this.datas.push(newNode); 25 | 26 | this.bubbleUp(); 27 | } 28 | 29 | bubbleUp() // Time Complexity O(log n) 30 | { 31 | let index = this.datas.length - 1; 32 | 33 | const elem = this.datas[index]; // 'data' will be stored in 'elem' 34 | 35 | while(index > 0) // Index must be greater than 0 36 | { 37 | let parentIndex = Math.floor((index - 1) / 2); // Parent Index 38 | let parent = this.datas[parentIndex]; // Parent index's data 39 | 40 | if(elem.priority >= parent.priority) break; 41 | // If the input 'data's priority is >= to data's priority in parent index, then we'll break out; 42 | 43 | // Otherwise we'll swap the values 44 | this.datas[parentIndex] = elem; // Will swap 'data' with parent index's data 45 | 46 | this.datas[index] = parent; // Then, new 'data' will be parent value 47 | 48 | index = parentIndex; // Update the index to parent index 49 | } 50 | } 51 | 52 | dequeue() // Time Complexity O(log n) 53 | { 54 | this.count--; 55 | let min = this.datas[0]; // Min data in Min ER 56 | 57 | let endData = this.datas.pop(); // Last data in Min ER 58 | 59 | let length = this.datas.length; 60 | if(length > 0) // if array length is greater than 0 61 | { 62 | this.datas[0] = endData; // The value of Min data is now 'endData' 63 | this.bubbleDown(); 64 | } 65 | 66 | console.log(`Currently "${min.value}" is the priority in Priority Queue`); 67 | 68 | return min; 69 | } 70 | 71 | bubbleDown() // Time Complexity O(log n) 72 | { 73 | let index = 0; 74 | 75 | const length = this.datas.length; 76 | 77 | const element = this.datas[0]; 78 | 79 | while(true) 80 | { 81 | let leftChildIndex = 2 * index + 1; 82 | let rightChildIndex = 2 * index + 2; 83 | 84 | let leftChild, rightChild; 85 | 86 | let swap = null; // It's going to keep track of the position, we'er going to swap with 87 | 88 | if(leftChildIndex < length) // leftChildIndex is inbound, then assign the value to the left child 89 | { 90 | leftChild = this.datas[leftChildIndex]; 91 | 92 | if(leftChild.priority < element.priority) // If leftChild is lesser than element then set swap equal to leftChildIndex 93 | { 94 | swap = leftChildIndex; 95 | } 96 | } 97 | 98 | if(rightChildIndex < length) // rightChildIndex is inbound, then assign the value to the right child 99 | { 100 | rightChild = this.datas[rightChildIndex]; 101 | 102 | if 103 | ( 104 | (swap === null && rightChild.priority < element.priority) || // If swap is still null & rightChild is lesser than element 105 | (swap !== null && rightChild.priority < leftChild.priority) // If swap isn't null & rightChild is lesser than leftChild 106 | ) 107 | { 108 | swap = rightChildIndex; // then set swap equal to rightChildIndex 109 | } 110 | } 111 | 112 | if(swap === null) break; 113 | 114 | // Otherwise we'll swap the values 115 | this.datas[index] = this.datas[swap]; // Will swap the data in 'swap's' index with parent data's index 116 | 117 | this.datas[swap] = element; // Then, new 'data' will be parent value 118 | 119 | index = swap; // Update the index to parent index 120 | } 121 | } 122 | 123 | size() 124 | { 125 | console.log(`Total datas in Priority Queue : ${this.count}`); 126 | } 127 | 128 | } 129 | 130 | // Space Complexity O(n) 131 | // Complete Binary Tree is required 132 | // Using Min Binary Heap approach 133 | 134 | /* 135 | let ER = new PriorityQueue(); 136 | 137 | ER.enqueue("High Fever", 4) 138 | ER.enqueue("Cold", 5); 139 | ER.enqueue("Scratch", 7); 140 | ER.enqueue("Back pain", 6); 141 | ER.enqueue("Car accident", 2); 142 | ER.enqueue("Critical situation", 1); 143 | ER.enqueue("Broken bone", 3); 144 | 145 | ER.size() 146 | 147 | ER.dequeue(); 148 | ER.dequeue(); 149 | ER.dequeue(); 150 | ER.dequeue(); 151 | ER.size(); 152 | */ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Md Mashroor Zilan Snigdho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Linked List/Circular Linked List/circularDoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | const DoublyLinkedList = require('../doublyLinkedList.js'); 2 | 3 | class CircularDoublyLinkedList extends DoublyLinkedList 4 | { 5 | 6 | printCircularLinkedList() 7 | { 8 | let current = this.head; 9 | 10 | console.log('Circular Singly Linked List:'); 11 | 12 | for (let i = 0; i < this.size; i++) 13 | { 14 | console.log(current); 15 | current = current.next; 16 | 17 | if(current.next === null) current.next = this.head; 18 | } 19 | } 20 | } 21 | 22 | // The lines below are not part of the data structure 23 | 24 | /* 25 | const circularDoublyLinkedList = new CircularDoublyLinkedList(); 26 | circularDoublyLinkedList.prepend(100); 27 | circularDoublyLinkedList.append(500); 28 | 29 | circularDoublyLinkedList.prepend(300); 30 | 31 | circularDoublyLinkedList.append(1000); 32 | 33 | circularDoublyLinkedList.insertAt(400,2); 34 | 35 | circularDoublyLinkedList.insertAt(200,0); 36 | 37 | circularDoublyLinkedList.length(); 38 | circularDoublyLinkedList.printData(); 39 | 40 | circularDoublyLinkedList.printLinkedList(); 41 | 42 | circularDoublyLinkedList.printCircularLinkedList(); 43 | 44 | circularDoublyLinkedList.getData(300); 45 | circularDoublyLinkedList.getData(3000); 46 | circularDoublyLinkedList.getIndex(4); 47 | 48 | circularDoublyLinkedList.removeIndex(2); 49 | 50 | circularDoublyLinkedList.length(); 51 | 52 | circularDoublyLinkedList.printData(); 53 | 54 | circularDoublyLinkedList.printCircularLinkedList(); 55 | 56 | circularDoublyLinkedList.clear(); 57 | 58 | circularDoublyLinkedList.length(); 59 | 60 | circularDoublyLinkedList.printData(); 61 | */ -------------------------------------------------------------------------------- /Linked List/Circular Linked List/circularSinglyLinkedList.js: -------------------------------------------------------------------------------- 1 | const SinglyLinkedList = require('../singlyLinkedList.js'); 2 | 3 | class CircularSinglyLinkedList extends SinglyLinkedList 4 | { 5 | 6 | printCircularLinkedList() 7 | { 8 | let current = this.head; 9 | 10 | console.log('Circular Singly Linked List:'); 11 | 12 | for (let i = 0; i < this.size; i++) 13 | { 14 | console.log(current); 15 | current = current.next; 16 | 17 | if(current.next === null) current.next = this.head; 18 | } 19 | } 20 | } 21 | 22 | // The lines below are not part of the data structure 23 | 24 | /* 25 | const circularSinglyLinkedList = new CircularSinglyLinkedList(); 26 | circularSinglyLinkedList.prepend(100); 27 | circularSinglyLinkedList.append(500); 28 | 29 | circularSinglyLinkedList.prepend(300); 30 | 31 | circularSinglyLinkedList.append(1000); 32 | 33 | circularSinglyLinkedList.insertAt(400,2); 34 | 35 | circularSinglyLinkedList.insertAt(200,0); 36 | 37 | circularSinglyLinkedList.length(); 38 | circularSinglyLinkedList.printData(); 39 | 40 | circularSinglyLinkedList.printLinkedList(); 41 | 42 | circularSinglyLinkedList.printCircularLinkedList(); 43 | 44 | circularSinglyLinkedList.getData(300); 45 | circularSinglyLinkedList.getData(3000); 46 | circularSinglyLinkedList.getIndex(4); 47 | 48 | circularSinglyLinkedList.removeIndex(2); 49 | 50 | circularSinglyLinkedList.length(); 51 | 52 | circularSinglyLinkedList.printData(); 53 | 54 | circularSinglyLinkedList.printCircularLinkedList(); 55 | 56 | circularSinglyLinkedList.clear(); 57 | 58 | circularSinglyLinkedList.length(); 59 | 60 | circularSinglyLinkedList.printData(); 61 | */ -------------------------------------------------------------------------------- /Linked List/Node/doublyNode.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(data, previous, next) 4 | { 5 | this.data = data; 6 | this.previous = previous || null; 7 | this.next = next || null; 8 | } 9 | } 10 | 11 | module.exports = Node; -------------------------------------------------------------------------------- /Linked List/Node/singlyNode.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(data, next = null) 4 | { 5 | this.data = data; 6 | this.next = next; 7 | } 8 | } 9 | 10 | module.exports = Node; -------------------------------------------------------------------------------- /Linked List/Sorted Linked List/sortedDoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | const DoublyLinkedList = require('../doublyLinkedList.js'); 2 | 3 | class SortedDoublyLinkedList extends DoublyLinkedList 4 | { 5 | sortLinkedList() 6 | { 7 | let current = this.head; 8 | let index = null; 9 | let temp; 10 | if(current === null) return; 11 | else 12 | { 13 | while(current !== null) 14 | { 15 | index = current.next; // Will point to the next value of current 16 | 17 | while(index !== null) 18 | { 19 | //The following 'if' block will sort ascending 20 | // Change '>' to '<' to sort descending 21 | if(current.data > index.data) 22 | { 23 | temp = current.data; 24 | current.data = index.data; 25 | index.data = temp; 26 | } 27 | index = index.next; 28 | } 29 | current = current.next; 30 | } 31 | } 32 | } 33 | 34 | printSortedLinkedListData() 35 | { 36 | let current = this.head; 37 | 38 | console.log('Sorted Data(s) of Linked List:'); 39 | 40 | for (let i = 0; i < this.size; i++) 41 | { 42 | console.log(`Data: ${current.data}`); 43 | current = current.next; 44 | } 45 | } 46 | } 47 | 48 | /* 49 | const sortedDoublyLinkedList = new SortedDoublyLinkedList(); 50 | sortedDoublyLinkedList.prepend(100); 51 | sortedDoublyLinkedList.prepend(250); 52 | sortedDoublyLinkedList.prepend(3000); 53 | 54 | sortedDoublyLinkedList.append(500); 55 | 56 | sortedDoublyLinkedList.insertAt(400,3); 57 | // singlyLinkedList.insertAt(700,8); // Successfully throws error 58 | sortedDoublyLinkedList.insertAt(700,5); 59 | sortedDoublyLinkedList.insertAt(800,0); 60 | 61 | sortedDoublyLinkedList.printData(); 62 | 63 | sortedDoublyLinkedList.printLinkedList(); 64 | 65 | sortedDoublyLinkedList.sortLinkedList(); 66 | 67 | sortedDoublyLinkedList.printSortedLinkedListData(); 68 | 69 | sortedDoublyLinkedList.printLinkedList(); 70 | */ -------------------------------------------------------------------------------- /Linked List/Sorted Linked List/sortedSinglyLinkedList.js: -------------------------------------------------------------------------------- 1 | const SinglyLinkedList = require('../singlyLinkedList.js'); 2 | 3 | class SortedSinglyLinkedList extends SinglyLinkedList 4 | { 5 | sortLinkedList() 6 | { 7 | let current = this.head; 8 | let index = null; 9 | let temp; 10 | if(current === null) return; 11 | else 12 | { 13 | while(current !== null) 14 | { 15 | index = current.next; // Will point to the next value of current 16 | 17 | while(index !== null) 18 | { 19 | //The following 'if' block will sort ascending 20 | // Change '>' to '<' to sort descending 21 | if(current.data > index.data) 22 | { 23 | temp = current.data; 24 | current.data = index.data; 25 | index.data = temp; 26 | } 27 | index = index.next; 28 | } 29 | current = current.next; 30 | } 31 | } 32 | } 33 | 34 | printSortedLinkedListData() 35 | { 36 | let current = this.head; 37 | 38 | console.log('Sorted Data(s) of Linked List:'); 39 | 40 | for (let i = 0; i < this.size; i++) 41 | { 42 | console.log(`Data: ${current.data}`); 43 | current = current.next; 44 | } 45 | } 46 | } 47 | 48 | /* 49 | const sortedSinglyLinkedList = new SortedSinglyLinkedList(); 50 | sortedSinglyLinkedList.prepend(100); 51 | sortedSinglyLinkedList.prepend(250); 52 | sortedSinglyLinkedList.prepend(3000); 53 | 54 | sortedSinglyLinkedList.append(500); 55 | 56 | sortedSinglyLinkedList.insertAt(400,3); 57 | // singlyLinkedList.insertAt(700,8); // Successfully throws error 58 | sortedSinglyLinkedList.insertAt(700,5); 59 | sortedSinglyLinkedList.insertAt(800,0); 60 | 61 | sortedSinglyLinkedList.printData(); 62 | 63 | sortedSinglyLinkedList.printLinkedList(); 64 | 65 | sortedSinglyLinkedList.sortLinkedList(); 66 | 67 | sortedSinglyLinkedList.printSortedLinkedListData(); 68 | 69 | sortedSinglyLinkedList.printLinkedList(); 70 | */ -------------------------------------------------------------------------------- /Linked List/doublyLinkedList.js: -------------------------------------------------------------------------------- 1 | const Node = require('./Node/doublyNode.js'); 2 | 3 | class DoublyLinkedList 4 | { 5 | constructor() 6 | { 7 | this.head = this.tail = null; 8 | this.size = 0; 9 | } 10 | 11 | prepend(data) // Time Complexity O(1) 12 | { 13 | if(!this.head) this.head = this.tail = new Node(data); 14 | else 15 | { 16 | let oldHead = this.head; 17 | this.head = new Node(data); 18 | oldHead.previous = this.head; 19 | this.head.next = oldHead; 20 | } 21 | 22 | this.size++; 23 | 24 | console.log(`Data '${data}' is PREPENDED `); 25 | } 26 | 27 | // Appends data 28 | append(data) // Time Complexity O(n) 29 | { 30 | // If empty, make head 31 | if(!this.tail) this.head = this.tail = new Node(data); 32 | else 33 | { 34 | let oldTail = this.tail; 35 | this.tail = new Node(data); 36 | oldTail.next = this.tail; 37 | this.tail.previous = oldTail; 38 | } 39 | 40 | this.size++; 41 | 42 | console.log(`Data '${data}' is APPENDED `); 43 | } 44 | 45 | // Prints Data(s) of Linked List 46 | printData() 47 | { 48 | let current = this.head; 49 | 50 | console.log('Linked List:'); 51 | 52 | for (let i = 0; i < this.size; i++) 53 | { 54 | console.log(`Data: ${current.data}`); 55 | current = current.next; 56 | } 57 | } 58 | 59 | // Prints Linked List 60 | printLinkedList() 61 | { 62 | let current = this.head; 63 | 64 | console.log('Linked List:'); 65 | 66 | for (let i = 0; i < this.size; i++) 67 | { 68 | console.log(current); 69 | current = current.next; 70 | } 71 | } 72 | 73 | insertAt(data, index) // Time Complexity O(n) 74 | { 75 | // If index is out of range 76 | this.outOfRange(index); 77 | 78 | // If first index 79 | if(index === 0) return this.prepend(data); 80 | 81 | const node = new Node(data); 82 | 83 | let current, previous; 84 | 85 | // Set current to first 86 | current = this.head; 87 | let count = 0; 88 | 89 | for(let count = 0; count < index; count++) 90 | { 91 | previous = current; // Node before index 92 | current = current.next; // Node after index 93 | } 94 | 95 | node.next = current; 96 | previous.next = node; 97 | 98 | this.size++; 99 | 100 | console.log(`Data '${data}' is INSERTED at index ${index}`); 101 | } 102 | 103 | // Gets the value of an index 104 | getIndex(index) 105 | { 106 | let current = this.head; 107 | let count = 0; 108 | 109 | for(let i =0; i < this.size; i++) 110 | { 111 | if(count === index) console.log(`Data at index ${index} is: ${current.data}`); 112 | count++; 113 | current = current.next; 114 | } 115 | 116 | if(index > count) console.log("Index doesn't exist"); 117 | } 118 | 119 | // Gets the index of an data 120 | getData(data) 121 | { 122 | let current = this.head; 123 | let index = -1; 124 | let found = 0; 125 | 126 | for(let i =0; i < this.size; i++) 127 | { 128 | index++; 129 | if(current.data === data) 130 | { 131 | found = 1; 132 | console.log(`Data ${current.data} is at index ${index}`); 133 | } 134 | current = current.next; 135 | } 136 | 137 | if(!found) console.log("Data doesn't exist");; 138 | } 139 | 140 | // Removes Index 141 | removeIndex(index) // Time Complexity O(n) 142 | { 143 | // If index is out of range 144 | this.outOfRange(index); 145 | 146 | let current = this.head; 147 | let previous; 148 | 149 | // Remove first 150 | if(this.head === 0) this.head = current.next; 151 | else 152 | { 153 | for(let count = 0; count < index; count++) 154 | { 155 | previous = current; 156 | current = current.next; 157 | } 158 | 159 | previous.next = current.next; 160 | } 161 | 162 | this.size--; 163 | 164 | console.log(`Data '${current.data}' is REMOVED from index ${index}`); 165 | } 166 | 167 | // Clears Linked list 168 | clear() 169 | { 170 | this.head = null; 171 | this.size = 0; 172 | } 173 | 174 | // If index is out of range 175 | outOfRange(index) 176 | { 177 | if(index > 0 && index > this.size) throw new RangeError("Index out of range"); 178 | } 179 | // Size of Linked List 180 | length() 181 | { 182 | console.log(`Length of Linked List: ${this.size}`); 183 | } 184 | 185 | // Reverses Linked list 186 | reverseLinkedList() 187 | { 188 | let current = this.head; 189 | let previous = null; 190 | let next = null; 191 | 192 | console.log('Reversed Linked List:') 193 | 194 | while (current !== null) 195 | { 196 | next = current.next; 197 | current.next = previous; 198 | console.log(current); 199 | previous = current; 200 | current = next; 201 | } 202 | this.head = previous; 203 | 204 | } 205 | } 206 | 207 | module.exports = DoublyLinkedList; 208 | // Space Complexity O(n) 209 | // The lines below are not part of the data structure 210 | 211 | /* 212 | const doublyLinkedList = new DoublyLinkedList(); 213 | 214 | doublyLinkedList.append(1); 215 | doublyLinkedList.append(2); 216 | doublyLinkedList.append(3); 217 | 218 | doublyLinkedList.prepend(100); 219 | 220 | doublyLinkedList.insertAt(400,3); 221 | //doublyLinkedList.insertAt(700,8); // Successfully throws error 222 | doublyLinkedList.prepend(50); 223 | 224 | doublyLinkedList.getData(1000); 225 | 226 | doublyLinkedList.length(); 227 | 228 | doublyLinkedList.printData(); 229 | 230 | doublyLinkedList.reverseLinkedList(); 231 | 232 | console.log('After reversing: '); 233 | doublyLinkedList.printData(); 234 | 235 | doublyLinkedList.getData(300); 236 | 237 | doublyLinkedList.removeIndex(3); 238 | 239 | doublyLinkedList.length(); 240 | 241 | doublyLinkedList.printData(); 242 | 243 | doublyLinkedList.printLinkedList(); 244 | 245 | doublyLinkedList.getData(100); 246 | 247 | doublyLinkedList.getIndex(2); 248 | doublyLinkedList.getIndex(9); 249 | 250 | doublyLinkedList.reverseLinkedList(); 251 | 252 | console.log('After reversing: '); 253 | doublyLinkedList.printData(); 254 | 255 | doublyLinkedList.clear(); 256 | doublyLinkedList.length(); 257 | 258 | doublyLinkedList.printLinkedList(); 259 | */ -------------------------------------------------------------------------------- /Linked List/singlyLinkedList.js: -------------------------------------------------------------------------------- 1 | const Node = require('./Node/singlyNode.js'); 2 | 3 | class SinglyLinkedList 4 | { 5 | constructor() 6 | { 7 | this.head = null; 8 | this.size = 0; 9 | } 10 | 11 | // Prepends data 12 | prepend(data) // Time Complexity O(1) 13 | { 14 | this.head = new Node(data, this.head); 15 | this.size++; 16 | 17 | console.log(`Data '${data}' is PREPENDED `); 18 | } 19 | 20 | // Appends data 21 | append(data) // Time Complexity O(n) 22 | { 23 | let node = new Node(data); 24 | let current; 25 | 26 | // If empty, make head 27 | if(!this.head) this.head = node; 28 | else 29 | { 30 | current = this.head; 31 | 32 | while (current.next) 33 | { 34 | current = current.next; // Traverse through the list 35 | } 36 | 37 | current.next = node; 38 | } 39 | 40 | this.size++; 41 | 42 | console.log(`Data '${data}' is APPENDED `); 43 | } 44 | 45 | // Inserts at any index 46 | insertAt(data, index) // Time Complexity O(n) 47 | { 48 | // If index is out of range 49 | this.outOfRange(index); 50 | 51 | // If first index 52 | if(index === 0) return this.prepend(data); 53 | 54 | const node = new Node(data); 55 | 56 | let current, previous; 57 | 58 | // Set current to first 59 | current = this.head; 60 | 61 | for(let count = 0; count < index; count++) 62 | { 63 | previous = current; // Node before index 64 | current = current.next; // Node after index 65 | } 66 | 67 | node.next = current; 68 | previous.next = node; 69 | 70 | this.size++; 71 | 72 | console.log(`Data '${data}' is INSERTED at index ${index}`); 73 | } 74 | 75 | // Gets the value of an index 76 | getIndex(index) 77 | { 78 | let current = this.head; 79 | let count = 0; 80 | 81 | for(let i =0; i < this.size; i++) 82 | { 83 | if(count === index) console.log(`Data at index ${index} is: ${current.data}`); 84 | count++; 85 | current = current.next; 86 | } 87 | 88 | if(index > count) console.log("Index doesn't exist"); 89 | } 90 | 91 | // Gets the index of an data 92 | getData(data) 93 | { 94 | let current = this.head; 95 | let index = -1; 96 | let found = 0; 97 | 98 | for(let i =0; i < this.size; i++) 99 | { 100 | index++; 101 | if(current.data === data) 102 | { 103 | found = 1; 104 | console.log(`Data ${current.data} is at index ${index}`); 105 | } 106 | current = current.next; 107 | } 108 | 109 | if(!found) console.log("Data doesn't exist");; 110 | } 111 | 112 | // Removes Index 113 | removeIndex(index) // Time Complexity O(n) 114 | { 115 | // If index is out of range 116 | this.outOfRange(index) 117 | 118 | let current = this.head; 119 | let previous; 120 | 121 | // Remove first 122 | if(this.head === 0) this.head = current.next; 123 | else 124 | { 125 | for(let count = 0; count < index; count++) 126 | { 127 | previous = current; 128 | current = current.next; 129 | } 130 | 131 | previous.next = current.next; 132 | } 133 | 134 | this.size--; 135 | 136 | console.log(`Data '${current.data}' is REMOVED from index ${index}`); 137 | } 138 | 139 | // Clears Linked list 140 | clear() 141 | { 142 | this.head = null; 143 | this.size = 0; 144 | } 145 | 146 | // Prints Data(s) of Linked List 147 | printData() 148 | { 149 | let current = this.head; 150 | 151 | console.log('Data(s) of Linked List:'); 152 | 153 | for (let i = 0; i < this.size; i++) 154 | { 155 | console.log(`Data: ${current.data}`); 156 | current = current.next; 157 | } 158 | } 159 | 160 | // Prints Linked List 161 | printLinkedList() 162 | { 163 | let current = this.head; 164 | 165 | console.log('Linked List:'); 166 | 167 | for (let i = 0; i < this.size; i++) 168 | { 169 | console.log(current); 170 | current = current.next; 171 | } 172 | } 173 | 174 | // If index is out of range 175 | outOfRange(index) 176 | { 177 | if(index > 0 && index > this.size) throw new RangeError("Index out of range"); 178 | } 179 | // Size of Linked List 180 | length() 181 | { 182 | console.log(`Length of Linked List: ${this.size}`); 183 | } 184 | 185 | // Reverses Linked list 186 | reverseLinkedList() 187 | { 188 | let current = this.head; 189 | let previous = null; 190 | let next = null; 191 | 192 | console.log('Reversed Linked List:') 193 | 194 | while (current !== null) 195 | { 196 | next = current.next; 197 | current.next = previous; 198 | console.log(current); 199 | previous = current; 200 | current = next; 201 | } 202 | this.head = previous; 203 | } 204 | } 205 | 206 | module.exports = SinglyLinkedList; 207 | // Space Complexity O(n) 208 | // The lines below are not part of the data structure 209 | 210 | /* 211 | const singlyLinkedList = new SinglyLinkedList(); 212 | singlyLinkedList.prepend(100); 213 | singlyLinkedList.prepend(200); 214 | singlyLinkedList.prepend(300); 215 | 216 | singlyLinkedList.append(500); 217 | 218 | singlyLinkedList.insertAt(400,3); 219 | // singlyLinkedList.insertAt(700,8); // Successfully throws error 220 | singlyLinkedList.insertAt(700,5); 221 | singlyLinkedList.insertAt(800,0); 222 | 223 | singlyLinkedList.getData(1000); 224 | 225 | singlyLinkedList.length(); 226 | 227 | singlyLinkedList.printData(); 228 | 229 | singlyLinkedList.reverseLinkedList(); 230 | 231 | console.log('After reversing: '); 232 | singlyLinkedList.printData(); 233 | 234 | singlyLinkedList.getData(300); 235 | 236 | singlyLinkedList.removeIndex(3); 237 | 238 | singlyLinkedList.length(); 239 | 240 | singlyLinkedList.printData(); 241 | 242 | singlyLinkedList.printLinkedList(); 243 | 244 | singlyLinkedList.getData(500); 245 | 246 | singlyLinkedList.getIndex(2); 247 | singlyLinkedList.getIndex(9); 248 | 249 | singlyLinkedList.reverseLinkedList(); 250 | 251 | console.log('After reversing: '); 252 | singlyLinkedList.printData(); 253 | 254 | singlyLinkedList.clear(); 255 | singlyLinkedList.length(); 256 | singlyLinkedList.printData(); 257 | */ -------------------------------------------------------------------------------- /Queue/circularQueue.js: -------------------------------------------------------------------------------- 1 | class CircularQueue 2 | { 3 | constructor(capacity) 4 | { 5 | this.list = []; 6 | this.head = 0; 7 | this.tail = 0; 8 | this.size = 0; 9 | this.capacity = capacity; 10 | } 11 | 12 | // Size of Queue 13 | length() 14 | { 15 | console.log(`Size of Queue: ${this.size}`); 16 | return this.size; 17 | } 18 | 19 | // Checks if queue is full 20 | isFull() 21 | { 22 | return this.size === this.capacity; 23 | } 24 | 25 | // Checks if Queue is empty 26 | isEmpty() 27 | { 28 | return this.size === 0; 29 | } 30 | 31 | // Adds element to the rear of the Queue 32 | enqueue(item) // Time Complexity O(1) 33 | { 34 | if(this.isFull()) 35 | { 36 | throw new Error("Queue is full"); 37 | } 38 | else 39 | { 40 | this.list[this.tail] = item; 41 | this.tail = (this.tail + 1) % this.capacity; 42 | this.size ++; 43 | 44 | } 45 | console.log(`Queued: ${item}`); 46 | return item; 47 | } 48 | 49 | // Removes element from the front of the Queue 50 | dequeue() // Time Complexity O(1) 51 | { 52 | let item = null; 53 | 54 | if(!this.isEmpty()) 55 | { 56 | item = this.list[this.head]; 57 | this.list[this.head] = null; 58 | this.head = (this.head + 1) % this.capacity; 59 | this.size --; 60 | } 61 | return item; 62 | } 63 | 64 | peek() 65 | { 66 | console.log(`Peek: ${this.list[this.head]}`) 67 | return this.list[this.head]; 68 | } 69 | 70 | // Print Queue 71 | print() 72 | { 73 | console.log(`Queue: ${this.list.filter(elem => elem !== null).join(' ')}`); 74 | } 75 | 76 | 77 | // Clear Queue 78 | clear() 79 | { 80 | console.log(`Queue cleared...`); 81 | this.size = 0; 82 | return this.list = []; 83 | } 84 | 85 | } 86 | 87 | // FIFO Principle (FIFO : First in First Out) 88 | // Space Complexity O(n) 89 | 90 | // The lines below are not part of the data structure 91 | 92 | /* 93 | const cirQueue = new CircularQueue(5); 94 | 95 | cirQueue.enqueue(15); 96 | cirQueue.enqueue(16); 97 | cirQueue.enqueue(17); 98 | cirQueue.enqueue(18); 99 | cirQueue.enqueue(19); 100 | //cirQueue.enqueue(20); 101 | 102 | cirQueue.print(); 103 | 104 | cirQueue.peek(); 105 | 106 | cirQueue.dequeue(); 107 | cirQueue.dequeue(); 108 | 109 | cirQueue.length(); 110 | 111 | cirQueue.peek(); 112 | 113 | cirQueue.enqueue(40); 114 | //cirQueue.enqueue(42); 115 | 116 | cirQueue.print(); 117 | cirQueue.length(); 118 | 119 | 120 | cirQueue.clear(); 121 | 122 | cirQueue.print(); 123 | 124 | cirQueue.length(); 125 | */ -------------------------------------------------------------------------------- /Queue/priorityQueue.js: -------------------------------------------------------------------------------- 1 | class PriorityQueue 2 | { 3 | constructor() 4 | { 5 | this.list = []; 6 | } 7 | 8 | // Adds element to the rear of the Queue 9 | enqueue(element) // Time Complexity O(1) 10 | { 11 | if(this.isEmpty()) 12 | { 13 | this.list.push(element); 14 | } 15 | else 16 | { 17 | let added = false; 18 | for(let i = 0; i < this.list.length; i++) 19 | { 20 | if(element[1] < this.list[i][1]) // Checking priorities 21 | { 22 | this.list.splice(i, 0 , element); 23 | added = true; 24 | break; 25 | } 26 | } 27 | if(!added) 28 | { 29 | this.list.push(element); 30 | } 31 | } 32 | } 33 | 34 | // Removes element from the front of the Queue 35 | dequeue() // Time Complexity O(n) 36 | { 37 | return this.list.shift(); 38 | } 39 | 40 | // Prints Queue 41 | print() 42 | { 43 | console.log(this.list); 44 | } 45 | 46 | // Checks if Queue is empty 47 | isEmpty() 48 | { 49 | return this.list.length === 0; 50 | } 51 | 52 | // Size of Queue 53 | size() 54 | { 55 | console.log(`Size of Queue: ${this.list.length}`); 56 | return this.list.length; 57 | } 58 | 59 | // Front value of Queue 60 | front() 61 | { 62 | console.log(`Front value: ${this.list[0]} `); 63 | return this.list[0]; 64 | } 65 | 66 | // Rear value of Queue 67 | rear() 68 | { 69 | console.log(`Rear value: ${this.list[this.list.length-1]} `); 70 | return this.list[this.list.length-1]; 71 | } 72 | 73 | // Clears Queue 74 | clear() 75 | { 76 | console.log('items cleared..') 77 | this.list.length = 0; 78 | return this.list = []; 79 | } 80 | } 81 | 82 | // FIFO Principle (FIFO : First in First Out) 83 | // Space Complexity O(n) 84 | 85 | // The lines below are not part of the data structure 86 | 87 | /* 88 | const priQueue = new PriorityQueue(); 89 | 90 | priQueue.enqueue(['etet',4]); 91 | priQueue.enqueue(['rye',5]); 92 | priQueue.enqueue(['wtw',2]); 93 | priQueue.enqueue(['rtur', 3]); 94 | priQueue.enqueue(['Xa',1]); 95 | 96 | priQueue.print(); 97 | priQueue.size(); 98 | 99 | priQueue.dequeue(); 100 | priQueue.size(); 101 | priQueue.print(); 102 | 103 | priQueue.front(); 104 | priQueue.rear(); 105 | 106 | priQueue.clear(); 107 | priQueue.print(); 108 | 109 | priQueue.size(); 110 | */ 111 | 112 | -------------------------------------------------------------------------------- /Queue/queue.js: -------------------------------------------------------------------------------- 1 | class Queue 2 | { 3 | constructor() 4 | { 5 | this.items = []; 6 | } 7 | 8 | // Adds element to the front of the Queue 9 | enqueue(element) // Time Complexity O(1) 10 | { 11 | console.log(`${element} enqueued`); 12 | return this.items.push(element); 13 | } 14 | 15 | // Removes element from the front of the Queue 16 | dequeue() // Time Complexity O(n) 17 | { 18 | let shiftedElem = this.items.shift(); 19 | console.log(`${shiftedElem} dequeued`); 20 | return shiftedElem; 21 | } 22 | 23 | // Front value of Queue 24 | front() 25 | { 26 | console.log(`Front value: ${this.items[0]} `); 27 | return this.items[0]; 28 | } 29 | 30 | // Rear value of Queue 31 | rear() 32 | { 33 | console.log(`Rear value: ${this.items[this.items.length-1]} `); 34 | return this.items[this.items.length-1]; 35 | } 36 | 37 | // Size of Queue 38 | size() 39 | { 40 | console.log(`Size of Queue: ${this.items.length}`); 41 | return this.items.length; 42 | } 43 | 44 | // Checks if Queue is empty 45 | isEmpty() 46 | { 47 | console.log(this.items.length === 0 ? 'Queue is empty' : 'Queue is NOT empty'); 48 | return this.items.length === 0; 49 | } 50 | 51 | // Prints Queue 52 | print() 53 | { 54 | let str = ''; 55 | 56 | if(this.items.length !== 0) 57 | { 58 | for(let i = 0; i< this.items.length; i++) 59 | { 60 | str += this.items[i] + ' '; 61 | } 62 | } 63 | else{str = '[EMPTY]'} 64 | 65 | return str; 66 | } 67 | 68 | // Clears Queue 69 | clear() 70 | { 71 | console.log('items cleared..') 72 | return this.items = []; 73 | } 74 | } 75 | 76 | // FIFO Principle (FIFO : First in First Out) 77 | // Space Complexity O(n) 78 | 79 | // The lines below are not part of the data structure 80 | 81 | /* 82 | const queue = new Queue(); 83 | 84 | queue.enqueue(1); 85 | queue.enqueue(2); 86 | queue.enqueue(3); 87 | 88 | queue.front(); 89 | 90 | queue.rear(); 91 | 92 | queue.size() 93 | 94 | console.log('Queue: ' + queue.print()); 95 | 96 | queue.dequeue() 97 | 98 | queue.size() 99 | 100 | console.log('Queue: ' + queue.print()); 101 | 102 | queue.isEmpty(); 103 | 104 | queue.clear(); 105 | 106 | queue.size(); 107 | console.log('Queue:' + queue.print()); 108 | */ 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome 2 | 3 | *You can find all the data structures & algorithms of this repository from the following index.* 4 | 5 | ## **Index** 6 | ### **Searching Algorithms** 7 | - **[Binary Search](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Searching/binarySearch.js)** 8 | 9 | - **[Linear Search](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Searching/linearSearch.js)** 10 | 11 | ### **Sorting Algorithms** 12 | - **[Bubble Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/bubbleSort.js)** 13 | 14 | - **[Insertion Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/insertionSort.js)** 15 | 16 | - **[Selection Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/selectionSort.js)** 17 | 18 | - **[Merge Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/mergeSort.js)** 19 | - **[Radix Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/radixSort.js)** 20 | #### Heap Sort 21 | - **[Max Heap Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/Heap%20Sort/maxHeapSort.js)** 22 | 23 | - **[Min Heap Sort](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/Heap%20Sort/minHeapSort.js)** 24 | 25 | #### Quick Sort 26 | - **[Quick Sort (Normal Approach)](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/Quick%20Sort/quickSort%20(Normal%20Approach).js)** 27 | 28 | - **[Quick Sort (Partition Approach)](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Sorting/Quick%20Sort/quickSort%20(Partition%20Approach).js)** 29 | ### **Stack** 30 | - **[Stack](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Stack/stack.js)** 31 | 32 | ### **Queue** 33 | - **[Queue](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Queue/queue.js)** 34 | 35 | - **[Priority Queue](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Queue/priorityQueue.js)** 36 | 37 | - **[Circular Queue](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Queue/circularQueue.js)** 38 | ### **Linked List** 39 | #### Node 40 | - **[Node for Singly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/Node/singlyNode.js)** 41 | 42 | - **[Node for Doubly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/Node/doublyNode.js)** 43 | #### Linked List 44 | - **[Singly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/singlyLinkedList.js)** 45 | 46 | - **[Doubly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/doublyLinkedList.js)** 47 | #### Circular Linked List 48 | - **[Circular Singly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/Circular%20Linked%20List/circularSinglyLinkedList.js)** 49 | 50 | - **[Circular Doubly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/Circular%20Linked%20List/circularDoublyLinkedList.js)** 51 | 52 | #### Sorted Linked List 53 | - **[Sorted Singly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/Sorted%20Linked%20List/sortedSinglyLinkedList.js)** 54 | 55 | - **[Sorted Doubly Linked List](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Linked%20List/Sorted%20Linked%20List/sortedDoublyLinkedList.js)** 56 | 57 | ### **Tree** 58 | #### Node 59 | - **[Node for Tree Data Structure](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Tree/Node/nodeTree.js)** 60 | 61 | #### Basic Tree 62 | - **[Basic Tree](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Tree/basicTree.js)** 63 | 64 | #### Binary Tree 65 | - **[Binary Tree](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Tree/Binary%20Tree/binaryTree.js)** 66 | - **[Binary Search Tree](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Tree/Binary%20Tree/binarySearchTree.js)** 67 | 68 | ### **Heap** 69 | #### Binary Heap 70 | - **[Max Binary Heap](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Heap/Binary%20Heap/maxBinaryHeap.js)** 71 | 72 | - **[Min Binary Heap](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Heap/Binary%20Heap/minBinaryHeap.js)** 73 | 74 | **[Priority Queue (Binary Heap approach)](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Heap/priorityQueue.js)** 75 | 76 | ### **Hash Table** 77 | **[Hash Table (Separate Chaining approach)](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Hash%20Table/hashTable.js)** 78 | 79 | ### **Graph** 80 | - **[Undirected Graph](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Graph/undirectedGraph.js)** 81 | 82 | - **[Directed Graph](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Graph/directedGraph.js)** 83 | 84 | ### **Dijkstra's Algorithm** 85 | **[Shortest Path Graph](https://github.com/mzs21/data-structures-algorithms-js/blob/main/Dijkstra's%20Algorithm/shortestPathGraph.js)** -------------------------------------------------------------------------------- /Searching/binarySearch.js: -------------------------------------------------------------------------------- 1 | const binarySearch = (ara,find) => 2 | { 3 | let left = 0; 4 | let right = ara.length; 5 | let mid; 6 | 7 | while(left <= right) // If 'left is '<=' to right, if it's true then, 8 | { 9 | mid = Math.floor((left + right) / 2); // we'll set the value of 'mid' to summation of left & right, divided by 2 10 | if (ara[mid] == find) return mid; // If the value located in the midth index of array is euqal to our desired 11 | // value then we'll return the index 12 | 13 | if (ara[mid] < find) left = mid + 1; // If the first 'if' fails, then we'll check if the midth index of array is 14 | // less than our desired value and set the value of 'left' to mid + 1 15 | else right = mid - 1; // Otherwise we'll set the value of 'right' to mid - 1; 16 | } 17 | return true; // If the 'while' condition fails, we'll just return true 18 | } 19 | 20 | // Time Complexity O(logn) 21 | // Space Complexity O(n) 22 | // Sorted array elements are required 23 | 24 | /* 25 | const input = require('prompt-sync')(); // Using to take input 26 | 27 | const arr = input('Values: '); // Will take input as string 28 | 29 | const newStr = arr.split(' '); // Will convert into an array 30 | 31 | const newArray = []; // Empty array 32 | 33 | for (let i = 0; i < newStr.length; i++) 34 | { 35 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 36 | } 37 | 38 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 39 | 40 | const element = Number(input(`The element I want to find: `)); 41 | 42 | const findNumber = binarySearch(newArray, element); 43 | 44 | if (findNumber !== true) console.log(`Number is found at index: ${Number(findNumber)}`); 45 | 46 | else console.log(`Number is not found`); 47 | */ -------------------------------------------------------------------------------- /Searching/linearSearch.js: -------------------------------------------------------------------------------- 1 | const linearSearch = (ara, find) => 2 | { 3 | for (let i = 0; i < ara.length; i++) // Will loop through the array 4 | { 5 | if(ara[i] === find) return i; // If the value we are looking for is found at the ith index of the array, 6 | // we'll return the index 7 | } 8 | return true; // Otherwise we'll return true 9 | } 10 | 11 | // Time Complexity O(n) 12 | // Space Complexity O(1) 13 | // Sorted array elements aren’t required. 14 | 15 | /* 16 | const input = require('prompt-sync')(); // Using to take input 17 | 18 | const arr = input('Values: '); // Will take input as string 19 | 20 | const newStr = arr.split(' '); // Will convert into an array 21 | 22 | const newArray = []; // Empty array 23 | 24 | for (let i = 0; i < newStr.length; i++) 25 | { 26 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 27 | } 28 | 29 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 30 | 31 | const element = Number(input(`The element I want to find: `)); 32 | 33 | const findNumber = linearSearch(newArray, element); 34 | 35 | if (findNumber !== true) console.log(`Number is found at index: ${Number(findNumber)}`); 36 | 37 | else console.log(`Number is not found`); 38 | */ -------------------------------------------------------------------------------- /Sorting/Heap Sort/maxHeapSort.js: -------------------------------------------------------------------------------- 1 | const maxHeapify = (arr, len, index) => // Time Complexity O(log n) 2 | { 3 | let max = index; // Parent Index 4 | let leftIndex = 2 * index + 1; // Left Index 5 | let rightIndex = 2 * index + 2; // Right Index 6 | 7 | if(leftIndex < len && arr[leftIndex] > arr[max]) // If left child of parent exists and is greater than max 8 | { 9 | max = leftIndex; 10 | } 11 | 12 | if(rightIndex < len && arr[rightIndex] > arr[max]) // If right child of parent exists and is greater than max 13 | { 14 | max = rightIndex; 15 | } 16 | 17 | if(max !== index) // If max is not parent index 18 | { 19 | [arr[index], arr[max]] = [arr[max], arr[index]]; // Swap values 20 | 21 | maxHeapify(arr, len, max); 22 | } 23 | return arr; 24 | } 25 | 26 | const maxHeapSort = (arr) => // Time Complexity O(n log n) 27 | { 28 | let length = arr.length; 29 | 30 | let lastParent = Math.floor(length / 2 - 1); 31 | let lastChild = length - 1; 32 | 33 | for(let i = lastParent; i >= 0; i--) 34 | { 35 | maxHeapify(arr, length, lastParent); // Building max heap 36 | } 37 | 38 | for(let i = lastChild; i > 0; i--) 39 | { 40 | [arr[0], arr[i]] = [arr[i], arr[0]]; // Swap parent with last node 41 | 42 | maxHeapify(arr, i, 0); // Again calling heapify on the reduced heap 43 | } 44 | 45 | return arr; 46 | } 47 | 48 | 49 | // Space Complexity O(1) 50 | // In-place algorithm 51 | 52 | /* 53 | 100 54 | / \ 55 | 52 43 56 | / \ / \ 57 | 33 47 10 35 58 | ------------------| | 59 | / \ ---------| 60 | 1 16 / 61 | 22 62 | */ 63 | 64 | // Max Heap: [100, 52, 43, 33, 47, 10, 35, 1, 16, 22] 65 | 66 | /* 67 | const input = require('prompt-sync')(); // Using to take input 68 | 69 | const arr = input('Values: '); // Will take input as string 70 | 71 | const newStr = arr.split(' '); // Will convert into an array 72 | 73 | const newArray = []; // Empty array 74 | 75 | for (let i = 0; i < newStr.length; i++) 76 | { 77 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 78 | } 79 | 80 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 81 | 82 | console.log(`Sorted Array: ${maxHeapSort(newArray).join(' ')}`); 83 | */ -------------------------------------------------------------------------------- /Sorting/Heap Sort/minHeapSort.js: -------------------------------------------------------------------------------- 1 | const minHeapify = (arr, len, index) => // Time Complexity O(log n) 2 | { 3 | let min = index; // Parent Index 4 | let leftIndex = 2 * index + 1; // Left Index 5 | let rightIndex = 2 * index + 2; // Right Index 6 | 7 | if(leftIndex < len && arr[leftIndex] < arr[min]) // If left child of parent exists and is less than min 8 | { 9 | min = leftIndex; 10 | } 11 | 12 | if(rightIndex < len && arr[rightIndex] < arr[min]) // If right child of parent exists and is less than min 13 | { 14 | min = rightIndex; 15 | } 16 | 17 | if(min !== index) // If min is not parent index 18 | { 19 | [arr[index], arr[min]] = [arr[min], arr[index]]; // Swap values 20 | 21 | minHeapify(arr, len, min); 22 | } 23 | return arr; 24 | } 25 | 26 | const minHeapSort = (arr) => // Time Complexity O(n log n) 27 | { 28 | let length = arr.length; 29 | 30 | let lastParent = Math.floor(length / 2 - 1); 31 | let lastChild = length - 1; 32 | 33 | for(let i = lastParent; i >= 0; i--) 34 | { 35 | minHeapify(arr, length, lastParent); // Building min heap 36 | } 37 | 38 | for(let i = lastChild; i > 0; i--) 39 | { 40 | [arr[0], arr[i]] = [arr[i], arr[0]]; // Swap parent with last node 41 | 42 | minHeapify(arr, i, 0); // Again calling minHeapify on the reduced heap 43 | } 44 | 45 | return arr; 46 | } 47 | 48 | // Space Complexity O(1) 49 | // In-place algorithm 50 | 51 | 52 | /* 53 | 1 54 | / \ 55 | 10 16 56 | / \ / \ 57 | 22 33 35 52 58 | ------------------| | 59 | / \ ---------| 60 | 43 47 / 61 | 100 62 | */ 63 | 64 | // Min Heap: [1, 10, 16, 22, 33, 35, 52, 43, 47, 100] 65 | 66 | /* 67 | const input = require('prompt-sync')(); // Using to take input 68 | 69 | const arr = input('Values: '); // Will take input as string 70 | 71 | const newStr = arr.split(' '); // Will convert into an array 72 | 73 | const newArray = []; // Empty array 74 | 75 | for (let i = 0; i < newStr.length; i++) 76 | { 77 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 78 | } 79 | 80 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 81 | 82 | console.log(`Sorted Array: ${minHeapSort(newArray).join(' ')}`); 83 | */ -------------------------------------------------------------------------------- /Sorting/Quick Sort/quickSort (Normal Approach).js: -------------------------------------------------------------------------------- 1 | const quickSort = (arr) => 2 | { 3 | if(arr.length <= 1) return arr; // If array's length is <= to 1, then just return the array; 4 | 5 | let pivot = arr[arr.length - 1]; 6 | 7 | let leftArr = []; 8 | let rightArr = []; 9 | 10 | for (let element = 0; element < arr.length - 1; element++) // This will loop through before the pivot element 11 | { 12 | arr[element] < pivot ? leftArr.push(arr[element]) : rightArr.push(arr[element]); 13 | } 14 | 15 | return [...quickSort(leftArr), pivot, ...quickSort(rightArr)]; // Will do recursive call untill the array is sorted 16 | } 17 | // This will print the array in ascending order, 18 | // to print the array in descending order replace '<' with '>' on line 12 19 | 20 | // Time Complexity O(n) 21 | // Space Complexity O(n) 22 | 23 | /* 24 | const input = require('prompt-sync')(); // Using to take input 25 | 26 | const arr = input('Values: '); // Will take input as string 27 | 28 | const newStr = arr.split(' '); // Will convert into an array 29 | 30 | const newArray = []; // Empty array 31 | 32 | for (let i = 0; i < newStr.length; i++) { 33 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 34 | } 35 | 36 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 37 | 38 | console.log(`Sorted Array (Ascending): ${quickSort(newArray).join(' ')}`); 39 | 40 | //console.log(`Sorted Array (Descending): ${quickSort(newArray).join(' ')}`); 41 | */ -------------------------------------------------------------------------------- /Sorting/Quick Sort/quickSort (Partition Approach).js: -------------------------------------------------------------------------------- 1 | const partition = (arr, start = 0, end = arr.length-1) => 2 | { 3 | let pivot = arr[start]; 4 | let indexToSwap = start; 5 | 6 | for(let elem = start + 1; elem < arr.length; elem++) 7 | { 8 | if(arr[elem] < pivot) 9 | { 10 | indexToSwap++; 11 | [arr[elem], arr[indexToSwap]] = [arr[indexToSwap], arr[elem]]; 12 | } 13 | } 14 | 15 | [arr[start], arr[indexToSwap]] = [arr[indexToSwap], arr[start]]; 16 | 17 | return indexToSwap; 18 | } 19 | 20 | const quickSort = (arr, left = 0, right = arr.length - 1) => 21 | { 22 | let pivotIndex; 23 | 24 | if(left < right) 25 | { 26 | pivotIndex = partition(arr, left, right); 27 | 28 | quickSort(arr, left, pivotIndex - 1); // Left array 29 | 30 | quickSort(arr, pivotIndex + 1, right); // Right array 31 | } 32 | 33 | return arr; 34 | } 35 | 36 | // This will print the array in ascending order, 37 | // to print the array in descending order replace '<' with '>' on line 8 38 | 39 | // Time Complexity O(n) 40 | // Space Complexity O(n) 41 | 42 | /* 43 | const input = require('prompt-sync')(); // Using to take input 44 | 45 | const arr = input('Values: '); // Will take input as string 46 | 47 | const newStr = arr.split(' '); // Will convert into an array 48 | 49 | const newArray = []; // Empty array 50 | 51 | for (let i = 0; i < newStr.length; i++) { 52 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 53 | } 54 | 55 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 56 | 57 | console.log(`Sorted Array (Ascending): ${quickSort(newArray).join(' ')}`); 58 | 59 | // console.log(`Sorted Array (Descending): ${quickSort(newArray).join(' ')}`); 60 | */ -------------------------------------------------------------------------------- /Sorting/bubbleSort.js: -------------------------------------------------------------------------------- 1 | const bubbleSort = (arr) => 2 | { 3 | for (let i = 0; i < arr.length; i++) 4 | { 5 | for (let j = 0; j < (arr.length)-i-1; j++) // This inner loop will loop before (arr.length)-i-1 6 | { 7 | if(arr[j] > arr[j+1]) // If this conditiion fulfills, then we'll swap the values 8 | { 9 | [arr[j], arr[j+1]] = [arr[j+1], arr[j]]; // Swapping values 10 | 11 | // This will print the array in ascending order, 12 | // to print the array in descending order replace '>' with '<' 13 | } 14 | } 15 | } 16 | return arr; 17 | } 18 | 19 | // Time Complexity O(n^2) 20 | // Space Complexity O(1) 21 | 22 | /* 23 | const input = require('prompt-sync')(); // Using to take input 24 | 25 | const arr = input('Values: '); // Will take input as string 26 | 27 | const newStr = arr.split(' '); // Will convert into an array 28 | 29 | const newArray = []; // Empty array 30 | 31 | for (let i = 0; i < newStr.length; i++) { 32 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 33 | } 34 | 35 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 36 | 37 | console.log(`Sorted Array (Ascending): ${bubbleSort(newArray).join(' ')}`); 38 | 39 | //console.log(`Sorted Array (Descending): ${bubbleSort(newArray).join(' ')}`); 40 | // To print in descending order, change '>' to '<' on line 7 41 | */ -------------------------------------------------------------------------------- /Sorting/insertionSort.js: -------------------------------------------------------------------------------- 1 | const insertionSort = (arr) => 2 | { 3 | let item; 4 | 5 | for(let i = 0; i < arr.length; i++) 6 | { 7 | item = arr[i]; // Will assign ith index of array to item 8 | 9 | let j = i-1; // We have to find the appropriate index to place the item 10 | // So, we will assign j to ith index - 1 11 | 12 | while(j >= 0 && arr[j] < item) // Index can't be lower than 0, so we'll check if the index of j is greater 13 | // than or equal to 0 & will also check if the value (arr[j]) is greater than item 14 | // If the condition fulfills, 15 | { 16 | arr[j+1] = arr[j]; // we'll assign (j+1)th index of array to array's jth index 17 | j--; // and reduce the value j to -1 so, the condition can be false & we can get out of this block 18 | } 19 | 20 | arr[j+1] = item; // Finally, we'll assign the value of (j+1)th index of array to item 21 | } 22 | return arr; // In the end, we'll return the array but this time it'll be sorted 23 | } 24 | 25 | // This will print the array in ascending order, 26 | // to print the array in descending order replace 'arr[j] > item' with 'arr[j] < item' 27 | 28 | // This Algo is good to use if the inputed array is alomost sorted or partially sorted 29 | // Time Complexity O(n^2) 30 | // Space Complexity O(1) 31 | 32 | /* 33 | const input = require('prompt-sync')(); // Using to take input 34 | 35 | const arr = input('Values: '); // Will take input as string 36 | 37 | const newStr = arr.split(' '); // Will convert into an array 38 | 39 | const newArray = []; // Empty array 40 | 41 | for (let i = 0; i < newStr.length; i++) { 42 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 43 | } 44 | 45 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 46 | 47 | console.log(`Sorted Array (Ascending): ${insertionSort(newArray).join(' ')}`); 48 | 49 | //console.log(`Sorted Array (Descending): ${insertionSort(newArray).join(' ')}`); 50 | */ -------------------------------------------------------------------------------- /Sorting/mergeSort.js: -------------------------------------------------------------------------------- 1 | const merge = (leftArr, rightArr) => 2 | { 3 | const result = []; // Array that will contain the final result 4 | 5 | let leftIndex = 0; 6 | let rightIndex = 0; 7 | 8 | while(leftIndex < leftArr.length && rightIndex < rightArr.length) 9 | { 10 | //Extracting elements 11 | const leftElem = leftArr[leftIndex]; 12 | const rightElem = rightArr[rightIndex]; 13 | 14 | if(leftElem < rightElem) // If left element is < right element then, push left element 15 | { // This will store the array in ascending order, to store in 16 | // descending order change '<' to '>' 17 | result.push(leftElem); 18 | leftIndex++; 19 | } 20 | else 21 | { 22 | result.push(rightElem); // Otherwise, push right element 23 | rightIndex++; 24 | } 25 | } 26 | /* 27 | // As we don't know which elements have been left behind from which array, so 28 | // we'll use spread operator to use the remaining unused elements. 29 | // We'll get either get elements from left array or right array but not from both. 30 | */ 31 | 32 | let finalResult = [...result, ...leftArr.slice(leftIndex), ...rightArr.slice(rightIndex)]; 33 | 34 | return finalResult; 35 | } 36 | // Time Complexity O(n) 37 | // Space Complexity O(n) 38 | 39 | const mergeSort = (arr) => 40 | { 41 | if(arr.length <= 1) return arr; // If array's length is <= to 1, then just return the array; 42 | 43 | // Otherwise.... 44 | const mid = Math.floor(arr.length / 2); 45 | const leftArr = arr.slice(0, mid); 46 | const rightArr = arr.slice(mid); 47 | 48 | return merge(mergeSort(leftArr), mergeSort(rightArr)); 49 | } 50 | 51 | // Time Complexity O(n log(n)) 52 | // Space Complexity O(n) 53 | 54 | /* 55 | const input = require('prompt-sync')(); // Using to take input 56 | 57 | const arr = input('Values: '); // Will take input as string 58 | 59 | const newStr = arr.split(' '); // Will convert into an array 60 | 61 | const newArray = []; // Empty array 62 | 63 | for (let i = 0; i < newStr.length; i++) { 64 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 65 | } 66 | 67 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 68 | 69 | console.log(`Sorted Array (Ascending): ${mergeSort(newArray).join(' ')}`); 70 | 71 | //console.log(`Sorted Array (Descending): ${mergeSort(newArray).join(' ')}`); 72 | // To print in descending order, change '<' to '>' on line 14 73 | */ -------------------------------------------------------------------------------- /Sorting/radixSort.js: -------------------------------------------------------------------------------- 1 | const getDigit = (num, i) => // Gets the digit in ith position of number 2 | { 3 | return Math.floor(Math.abs(num) / Math.pow(10, i)) % 10; 4 | } 5 | 6 | const digitCount = (num) => // Counts the length of a number 7 | { 8 | if(num === 0) return 1; 9 | return Math.floor(Math.log10(Math.abs(num))) + 1; 10 | } 11 | 12 | const mostDigits = (numsArr) => // Finds the number having the highest length 13 | { 14 | let maxDigits = 0 15 | 16 | for(let i = 0; i < numsArr.length; i++) 17 | { 18 | maxDigits = Math.max(maxDigits, digitCount(numsArr[i])); 19 | } 20 | 21 | return maxDigits; 22 | } 23 | 24 | const radixSort = (numsArr) => 25 | { 26 | let maxDigitCount = mostDigits(numsArr); // Counts the max length of among the numbers 27 | 28 | for(let k = 0; k < maxDigitCount; k++) 29 | { 30 | let digitBuckets = Array.from({length : 10}, () => []); // An array of 10 arrays 31 | 32 | for(let i = 0; i < numsArr.length; i++) 33 | { 34 | let digit = getDigit(numsArr[i], k); 35 | 36 | digitBuckets[digit].push(numsArr[i]); // Pushing the number according to ith position everytime 37 | } 38 | numsArr = [].concat(...digitBuckets); // Combining all sub arrays 39 | } 40 | return numsArr; 41 | } 42 | // This will print the array in ascending order, 43 | // to print the array in descending order replace '...digitBuckets' 44 | // with '...digitBuckets.reverse()' on line 38 45 | 46 | // Time Complexity O(nk) 47 | // Space Complexity O(n + k) 48 | 49 | /* 50 | const input = require('prompt-sync')(); // Using to take input 51 | 52 | const arr = input('Values: '); // Will take input as string 53 | 54 | const newStr = arr.split(' '); // Will convert into an array 55 | 56 | const newArray = []; // Empty array 57 | 58 | for (let i = 0; i < newStr.length; i++) 59 | { 60 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 61 | } 62 | 63 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 64 | 65 | console.log(`Sorted Array (Ascending): ${radixSort(newArray).join(' ')}`); 66 | 67 | // console.log(`Sorted Array (Descending): ${radixSort(newArray).join(' ')}`); 68 | */ -------------------------------------------------------------------------------- /Sorting/selectionSort.js: -------------------------------------------------------------------------------- 1 | const selectionSort = (arr) => 2 | { 3 | let index; // This sorting algo wokrs by swaping the value of indexes 4 | 5 | for (let i = 0; i < (arr.length)-1; i++) // Will loop before the (arr.length)-1 6 | { 7 | index = i; // Set the value of index to 'i' 8 | for(let j = i+1; j < arr.length; j++) 9 | { 10 | if(arr[j] < arr[index]) // If the value of jth index of the array is less than the value of 11 | { 12 | index = j; // 'index' of the array, then we set the value of index to j 13 | } 14 | } 15 | 16 | if(index != i) // If the index is not equal to i, 17 | { 18 | [arr[i], arr[index]] = [arr[index], arr[i]]; // then, we'll swap the value 19 | } 20 | } 21 | return arr; // This array will be sorted 22 | } 23 | 24 | // This will print the array in ascending order, 25 | // to print the array in descending order replace '<' with '>' on line 10 26 | 27 | // Time Complexity O(n^2) 28 | // Space Complexity O(1) 29 | 30 | /* 31 | const input = require('prompt-sync')(); // Using to take input 32 | 33 | const arr = input('Values: '); // Will take input as string 34 | 35 | const newStr = arr.split(' '); // Will convert into an array 36 | 37 | const newArray = []; // Empty array 38 | 39 | for (let i = 0; i < newStr.length; i++) { 40 | newArray.push(Number(newStr[i])); // Will convert the string elements to numbers 41 | } 42 | 43 | console.log(`Array: ${newArray.join(' ')}`); // This array will be of integers 44 | 45 | console.log(`Sorted Array (Ascending): ${selectionSort(newArray).join(' ')}`); 46 | 47 | //console.log(`Sorted Array (Descending): ${selectionSort(newArray).join(' ')}`); 48 | */ -------------------------------------------------------------------------------- /Stack/stack.js: -------------------------------------------------------------------------------- 1 | class Stack 2 | { 3 | constructor() 4 | { 5 | this.items = []; 6 | this.count = 0; 7 | } 8 | 9 | // Adds element to the top of the stack 10 | 11 | push(element) // Time Complexity O(1) 12 | { 13 | this.items[this.count] = element; 14 | console.log(`${element} added to ${this.count}`) 15 | this.count += 1; 16 | return this.count - 1; 17 | } 18 | 19 | // Returns and removes top element in stack 20 | // Returns undefined if stack is empty 21 | 22 | pop() // Time Complexity O(1) 23 | { 24 | if(this.count === 0) return undefined; 25 | 26 | let deleteItm = this.items[this.count - 1]; 27 | console.log(`${deleteItm} removed`) 28 | this.count--; 29 | return deleteItm; 30 | } 31 | 32 | // Checks top element in stack 33 | 34 | peek() 35 | { 36 | console.log(`Top element in stack ${this.items[this.count - 1]}`); 37 | return this.items[this.count - 1]; 38 | } 39 | 40 | // Checks if stack is empty 41 | 42 | isEmpty() 43 | { 44 | console.log(this.count === 0 ? 'Stack is empty' : 'Stack is NOT empty'); 45 | return this.count === 0; 46 | } 47 | 48 | // Stacks size 49 | 50 | size() 51 | { 52 | console.log(`Stack size ${this.count}`) 53 | return this.count; 54 | } 55 | 56 | print() 57 | { 58 | let str = ''; 59 | 60 | if(this.count != 0) 61 | { 62 | for(let i = 0; i< this.count; i++) 63 | { 64 | str += this.items[i] + ' '; 65 | } 66 | } 67 | else{str = '[EMPTY]'} 68 | 69 | return str; 70 | } 71 | 72 | // Clears stack 73 | 74 | clear() 75 | { 76 | this.items = []; 77 | this.count = 0; 78 | 79 | console.log('Stack cleared...'); 80 | 81 | return this.items; 82 | } 83 | } 84 | 85 | // LIFO Principle (LIFO: Last in First Out) 86 | 87 | // Space Complexity O(n) 88 | 89 | // The lines below are not part of the data structure 90 | 91 | /* 92 | const stack = new Stack(); 93 | 94 | 95 | stack.isEmpty(); 96 | stack.push(100); 97 | stack.push(200); 98 | 99 | stack.peek(); 100 | stack.push(300); 101 | 102 | console.log('Stack: ' + stack.print()) 103 | 104 | stack.pop(); 105 | 106 | stack.size(); 107 | 108 | console.log('Stack: ' + stack.print()) 109 | 110 | stack.clear(); 111 | stack.size(); 112 | 113 | console.log('Stack: ' + stack.print()) 114 | 115 | */ -------------------------------------------------------------------------------- /Tree/Binary Tree/binarySearchTree.js: -------------------------------------------------------------------------------- 1 | const Node = require('../Node/nodeTree.js'); 2 | 3 | class BianrySearchTree 4 | { 5 | constructor(data) 6 | { 7 | this.root = new Node(data); 8 | this.count = 1; 9 | } 10 | 11 | size() 12 | { 13 | console.log(`Total Nodes: ${this.count}`); 14 | return this.count; 15 | } 16 | 17 | insert(data) // Time Complexity O(n) 18 | { 19 | this.count++; 20 | 21 | let newNode = new Node(data); 22 | 23 | const searchTree = node => 24 | { 25 | if(data <= node.data) // Go left 26 | { 27 | if(!node.left) 28 | { 29 | node.left = newNode; // If no left child, append node 30 | 31 | console.log(`${data} inserted to Node ${node.data} as left child`); 32 | } 33 | else searchTree(node.left); // If left child exists, look left again 34 | } 35 | 36 | else if(data > node.data) // Go right 37 | { 38 | if(!node.right) 39 | { 40 | node.right = newNode; // If no right child, append node 41 | 42 | console.log(`${data} inserted to Node ${node.data} as right child`); 43 | } 44 | else searchTree(node.right); // If right child exists, look right again 45 | } 46 | } 47 | 48 | searchTree(this.root); 49 | } 50 | 51 | remove(data) // Time Complexity O(n) 52 | { 53 | console.log(`${data} removed from Tree`); 54 | 55 | const removeNode = (node,data) => 56 | { 57 | if(node === null) return null; 58 | if(data === node.data) 59 | { 60 | // Case 1: If node has no children 61 | if(node.left === null && node.right === null) return null; 62 | 63 | // Case 2: If node has no left child 64 | if(node.left === null) return node.right; 65 | 66 | // Case 3: If node has no right child 67 | if(node.right === null) return node.left; 68 | 69 | // Case 4: If node has 2 children 70 | 71 | let tempNode = node.right; 72 | 73 | while(tempNode.left !== null) tempNode = tempNode.left; 74 | 75 | node.data = tempNode.data; 76 | node.right = removeNode(node.right, tempNode.data) 77 | return node; 78 | } 79 | 80 | else if(data < node.data) 81 | { 82 | node.left = removeNode(node.left, data); 83 | return node; 84 | } 85 | 86 | else 87 | { 88 | node.right = removeNode(node.right, data); 89 | return node; 90 | } 91 | } 92 | 93 | this.root = removeNode(this.root, data); 94 | } 95 | 96 | min() // Finds the minimum value in the tree 97 | { 98 | let currentNode = this.root; 99 | 100 | while(currentNode.left) // Continue traversing through left until no more children 101 | { 102 | currentNode = currentNode.left; 103 | } 104 | console.log(`Minimum data: ${currentNode.data}`); 105 | return currentNode.data; 106 | } 107 | 108 | max() // Finds the maximum value in the tree 109 | { 110 | let currentNode = this.root; 111 | 112 | while(currentNode.right) // Continue traversing through right until no more children 113 | { 114 | currentNode = currentNode.right; 115 | } 116 | console.log(`Maximum data: ${currentNode.data}`); 117 | return currentNode.data; 118 | } 119 | 120 | contains(data) // Time Complexity O(n) 121 | { 122 | let currentNode = this.root; 123 | 124 | while(currentNode) 125 | { 126 | if(data === currentNode.data) 127 | { 128 | console.log(`Data: '${data}' exists`); 129 | return true; 130 | } 131 | if(data <= currentNode.data) currentNode = currentNode.left; 132 | else currentNode = currentNode.right; 133 | 134 | } 135 | 136 | console.log(`Data: '${data}' doesn't exist`); 137 | return false; 138 | } 139 | 140 | printTree() 141 | { 142 | let nodes = []; 143 | let queue = []; 144 | 145 | queue.push(this.root); 146 | 147 | while(queue.length) 148 | { 149 | let currentNode = queue.shift(); 150 | 151 | nodes.push(currentNode); 152 | 153 | if(currentNode.left) queue.push(currentNode.left); 154 | 155 | if(currentNode.right) queue.push(currentNode.right); 156 | } 157 | 158 | nodes.forEach(node => console.log(node)); 159 | return nodes; 160 | } 161 | 162 | findMinHeight(node = this.root) // Finds minimum height in the tree 163 | { 164 | if(node === null) return -1; 165 | 166 | let left = this.findMinHeight(node.left); 167 | let right = this.findMinHeight(node.right); 168 | 169 | if(left < right) return left + 1; 170 | else return right + 1; 171 | 172 | } 173 | 174 | findMaxHeight(node = this.root) // Finds maximum height in the tree 175 | { 176 | if(node === null) return -1; 177 | 178 | let left = this.findMaxHeight(node.left); 179 | let right = this.findMaxHeight(node.right); 180 | 181 | if(left > right) return left + 1; 182 | else return right + 1; 183 | } 184 | 185 | isBalanced() // Checks if the tree is balanced or not 186 | { 187 | this.findMinHeight() >= this.findMaxHeight() - 1 ? 188 | console.log(`Balanced ? Yes`) : 189 | console.log(`Balanced ? No`); 190 | 191 | return (this.findMinHeight() >= this.findMaxHeight() - 1); 192 | } 193 | 194 | // Depth first search - Looking branch by branch 195 | 196 | preOrder() // Root, Left, Right 197 | { 198 | let nodes = []; 199 | 200 | const traverse = node => 201 | { 202 | nodes.push(node.data); // Push root data 203 | 204 | if(node.left) traverse(node.left); // If left child exists, go left again 205 | 206 | if(node.right) traverse(node.right); // If right child exists, go right again 207 | } 208 | 209 | traverse(this.root); 210 | 211 | console.log(`Pre-order Traversal: ${nodes.join(' ')}`); 212 | return nodes; 213 | } 214 | 215 | inOrder() // Left, Root, Right 216 | { 217 | let nodes = []; 218 | 219 | const traverse = node => 220 | { 221 | if(node.left) traverse(node.left); // If left child exists, go left again 222 | 223 | nodes.push(node.data); // Push root data 224 | 225 | if(node.right) traverse(node.right); // If right child exists, go right again 226 | } 227 | 228 | traverse(this.root); 229 | 230 | console.log(`In-order Traversal: ${nodes.join(' ')}`); 231 | return nodes; 232 | } 233 | 234 | postOrder() // Left, Right, Root 235 | { 236 | let nodes = []; 237 | 238 | const traverse = node => 239 | { 240 | if(node.left) traverse(node.left); // If left child exists, go left again 241 | 242 | if(node.right) traverse(node.right); // If right child exists, go right again 243 | 244 | nodes.push(node.data); // Push root data 245 | } 246 | 247 | traverse(this.root); 248 | 249 | console.log(`Post-order Traversal: ${nodes.join(' ')}`); 250 | return nodes; 251 | } 252 | 253 | // Breadth first search - Looking level by level 254 | 255 | BFS() 256 | { 257 | let nodes = []; 258 | let queue = []; 259 | 260 | queue.push(this.root); 261 | 262 | while(queue.length) 263 | { 264 | let currentNode = queue.shift(); 265 | 266 | nodes.push(currentNode.data); 267 | 268 | if(currentNode.left) queue.push(currentNode.left); 269 | 270 | if(currentNode.right) queue.push(currentNode.right); 271 | } 272 | 273 | console.log(`BFS Traversal: ${nodes.join(' ')}`); 274 | return nodes; 275 | } 276 | } 277 | 278 | // Space Complexity O(n) 279 | 280 | // BST is a type of Binary Tree where, Left (Subtree) < Root < Right (Subtree) 281 | // Exception, a child can be equal to parent and in that case it's 282 | // either, Left (Subtree) <= Root < Right (Subtree) or Left (Subtree) < Root <= Right (Subtree) 283 | // It's an ordered tree 284 | 285 | /* 286 | 50 287 | / \ 288 | 40 70 289 | / \ / \ 290 | 40 45 65 90 291 | ----------------------| |---------------------- 292 | / \ / \ 293 | 42 48 63 67 294 | */ 295 | 296 | /* 297 | const bst = new BianrySearchTree(50); // Root / Level 0 298 | 299 | // Level 1 nodes 300 | bst.insert(40); 301 | bst.insert(70); 302 | 303 | // Level 2 nodes 304 | bst.insert(40); 305 | bst.insert(45); 306 | 307 | bst.insert(65); 308 | bst.insert(90); 309 | 310 | // Level 3 nodes 311 | bst.insert(42); 312 | bst.insert(48); 313 | 314 | bst.insert(63); 315 | bst.insert(67); 316 | 317 | bst.size(); 318 | 319 | bst.min(); 320 | bst.max(); 321 | 322 | bst.printTree(); 323 | 324 | console.log('Minimum height: ' + bst.findMinHeight()); 325 | console.log('Maximum height: ' + bst.findMaxHeight()); 326 | bst.isBalanced(); 327 | 328 | 329 | bst.contains(40); 330 | bst.contains(98); 331 | 332 | bst.preOrder(); 333 | 334 | bst.inOrder(); 335 | 336 | bst.postOrder(); 337 | 338 | bst.BFS(); 339 | 340 | bst.remove(45); 341 | 342 | bst.contains(45); 343 | 344 | bst.printTree(); 345 | 346 | console.log('Minimum height: ' + bst.findMinHeight()); 347 | console.log('Maximum height: ' + bst.findMaxHeight()); 348 | bst.isBalanced(); 349 | */ -------------------------------------------------------------------------------- /Tree/Binary Tree/binaryTree.js: -------------------------------------------------------------------------------- 1 | const Node = require('../Node/nodeTree.js'); 2 | 3 | class BianryTree extends Node 4 | { 5 | printTree(root) 6 | { 7 | let queue = [root]; 8 | 9 | while(queue.length > 0) 10 | { 11 | let currentNode = queue.shift(); 12 | 13 | console.log(currentNode); 14 | 15 | if(currentNode.left) queue.push(currentNode.left); 16 | 17 | if(currentNode.right) queue.push(currentNode.right); 18 | } 19 | } 20 | 21 | // Depth first search - Looking branch by branch 22 | 23 | preOrder(root) // Root, Left, Right 24 | { 25 | let nodes = []; 26 | 27 | const traverse = node => 28 | { 29 | nodes.push(node.data); // Push root data 30 | 31 | if(node.left) traverse(node.left); // If left child exists, go left again 32 | 33 | if(node.right) traverse(node.right); // If right child exists, go right again 34 | } 35 | 36 | traverse(root); 37 | 38 | console.log(`Pre-order Traversal: ${nodes.join(' ')}`); 39 | return nodes; 40 | } 41 | 42 | inOrder(root) // Left, Root, Right 43 | { 44 | let nodes = []; 45 | 46 | const traverse = node => 47 | { 48 | if(node.left) traverse(node.left); // If left child exists, go left again 49 | 50 | nodes.push(node.data); // Push root data 51 | 52 | if(node.right) traverse(node.right); // If right child exists, go right again 53 | } 54 | 55 | traverse(root); 56 | 57 | console.log(`In-order Traversal: ${nodes.join(' ')}`); 58 | return nodes; 59 | } 60 | 61 | postOrder(root) // Left, Right, Root 62 | { 63 | let nodes = []; 64 | 65 | const traverse = node => 66 | { 67 | if(node.left) traverse(node.left); // If left child exists, go left again 68 | 69 | if(node.right) traverse(node.right); // If right child exists, go right again 70 | 71 | nodes.push(node.data); // Push root data 72 | } 73 | 74 | traverse(root); 75 | 76 | console.log(`Post-order Traversal: ${nodes.join(' ')}`); 77 | return nodes; 78 | } 79 | 80 | // Breadth first search - Looking level by level 81 | 82 | BFS(root) 83 | { 84 | let queue = [root]; 85 | let nodes = []; 86 | 87 | while(queue.length > 0) 88 | { 89 | let currentNode = queue.shift(); 90 | 91 | nodes.push(currentNode.data); 92 | 93 | if(currentNode.left) queue.push(currentNode.left); 94 | 95 | if(currentNode.right) queue.push(currentNode.right); 96 | } 97 | 98 | console.log(`BFS Traversal: ${nodes.join(' ')}`); 99 | return nodes; 100 | } 101 | } 102 | 103 | // Space Complexity O(n) 104 | 105 | /* 106 | 2 107 | / \ 108 | 7 5 109 | / \ / \ 110 | 2 6 9 111 | -----------------------| |------------ 112 | / \ / \ 113 | 5 11 4 114 | */ 115 | 116 | /* 117 | // Root / Level 0 118 | const root = new BianryTree(2); // Root / Level 0 119 | 120 | // Level 1 nodes 121 | 122 | const seven = new Node(7); 123 | const fiveForRoot = new Node(5); 124 | 125 | root.left = seven; 126 | root.right = fiveForRoot; 127 | 128 | // Level 2 nodes 129 | 130 | const two = new Node(2); 131 | const six = new Node(6); 132 | const nine = new Node(9); 133 | 134 | seven.left = two; 135 | seven.right = six; 136 | 137 | fiveForRoot.right = nine; 138 | 139 | // Level 3 nodes 140 | const five = new Node(5); 141 | const eleven = new Node(11); 142 | const four = new Node(4); 143 | 144 | six.left = five; 145 | six.right = eleven; 146 | 147 | nine.left = four; 148 | 149 | //root.printTree(root); 150 | 151 | // You can check specific child nodes too 152 | 153 | //console.log(six); 154 | 155 | //console.log(nine); 156 | 157 | root.preOrder(root); 158 | 159 | root.inOrder(root); 160 | 161 | root.postOrder(root); 162 | 163 | root.BFS(root); 164 | */ -------------------------------------------------------------------------------- /Tree/Node/nodeTree.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(data) 4 | { 5 | this.data = data; 6 | this.left = null; 7 | this.right = null; 8 | } 9 | } 10 | 11 | module.exports = Node; -------------------------------------------------------------------------------- /Tree/basicTree.js: -------------------------------------------------------------------------------- 1 | class Tree 2 | { 3 | constructor(data) 4 | { 5 | this.data = data; 6 | } 7 | } 8 | 9 | /* 10 | a 11 | ____|____ 12 | / | \ 13 | b c d 14 | | / \ 15 | e f g 16 | */ 17 | 18 | /* 19 | const a = new Tree('a'); 20 | const b = new Tree('b'); 21 | const c = new Tree('c'); 22 | const d = new Tree('d'); 23 | const e = new Tree('e'); 24 | const f = new Tree('f'); 25 | const g = new Tree('g'); 26 | 27 | a.b = b; 28 | a.c = c; 29 | a.d = d; 30 | 31 | c.e = e; 32 | 33 | d.f = f; 34 | d.g = g; 35 | 36 | console.log(a); 37 | */ --------------------------------------------------------------------------------