UNPKG

ds-algo-study

Version:

Just experimenting with publishing a package

256 lines (176 loc) 4.68 kB
# Example Graph ### Visual Aid --- ## ![picture alt](https://s3-us-west-1.amazonaws.com/appacademy-open-assets/data_structures_algorithms/graphs/images/graphs.png) --- ### Example Code --- ```js class GraphNode { constructor(val) { this.val = val; this.neighbors = []; } } let a = new GraphNode("a"); let b = new GraphNode("b"); let c = new GraphNode("c"); let d = new GraphNode("d"); let e = new GraphNode("e"); let f = new GraphNode("f"); a.neighbors = [b, c, e]; c.neighbors = [b, d]; e.neighbors = [a]; f.neighbors = [e]; ``` --- --- # Basics - A graph is **any** collection of nodes and edges. - Much more relaxed in structure than a tree. - It doesn't have to have a root node (so not every node can be accessed from a single node) - It could have cycles (a group of nodes whose paths begin and end at the same node) - Any number of edges may leave a node --- # Ways To Reference a Graph Data Structure ## Visual Reference --- ## ![picture alt](https://s3-us-west-1.amazonaws.com/appacademy-open-assets/data_structures_algorithms/graphs/images/adj_matrix_graph.png) --- ## Adjacency Matrix --- The row index will corespond to the source of an edge and the column index will correspond to the edges destination. - When the edges have a direction, `matrix[i][j]` may not be the same as `matrix[j][i]` - It is common to say that a node is adjacent to itself so matrix[x][x] is true for any node - Will be O(n^2) space complexity --- ### A 2D Array as the method of storing the location of Nodes let matrix = [ | | **A** | **B** | **C** | **D** | **E** | **F** | | ----- | ------- | ------ | ------ | ------ | ------ | ------ | | **A** | [True, | True, | True, | False, | True, | False] | | **B** | [False, | True, | False, | False, | False, | False] | | **C** | [False, | True, | True, | True, | False, | False] | | **D** | [False, | False, | False, | True, | False, | False] | | **E** | [True, | False, | False, | False, | True, | False] | | **F** | [False, | False, | False, | False, | True, | True] | ]; --- ## Adjacency List --- Seeks to solve the shortcomings of the matrix implementation. It uses an object where keys represent node labels and values associated with that key are the adjacent nodes. --- ```js let graph = { a: ["b", "c", "e"], b: [], c: ["b", "d"], d: [], e: ["a"], f: ["e"], }; ``` --- # Graph Traversal ## Depth First --- ### With a Node Class --- #### Node Class Example - There may not always be a suitable root-like starting point. But in this example all the nodes can be traversed to in some way from the "f" node ```js class GraphNode { constructor(val) { this.val = val; this.neighbors = []; } } let a = new GraphNode("a"); let b = new GraphNode("b"); let c = new GraphNode("c"); let d = new GraphNode("d"); let e = new GraphNode("e"); let f = new GraphNode("f"); a.neighbors = [e, c, b]; c.neighbors = [b, d]; e.neighbors = [a]; f.neighbors = [e]; ``` --- --- #### Recursive Traversal ```js function depthFirstRecur(node, visited = new Set()) { if (visited.has(node.val)) return; console.log(node.val); visited.add(node.val); node.neighbors.forEach((neighbor) => { depthFirstRecur(neighbor, visited); }); } depthFirstRecur(f); // starting with f as it is a node that can reach all other nodes ``` #### Iterative Traversal ```js function depthFirstIter(node) { let visited = new Set(); let stack = [node]; while (stack.length) { let node = stack.pop(); if (visited.has(node.val)) continue; console.log(node.val); visited.add(node.val); stack.push(...node.neighbors); } } depthFirstIter(f); ``` --- --- ### With an Adjacency List --- #### Adjacency List Example Remember that the nodes are stored as strings in an array in an object. ```js let graph = { a: ["b", "c", "e"], b: [], c: ["b", "d"], d: [], e: ["a"], f: ["e"], }; ``` --- --- #### Recursive Example ```js function depthFirstRecur(node, graph, visited = new Set()) { if (visited.has(node)) return; console.log(node); visited.add(node); graph[node].forEach((neighbor) => { depthFirstRecur(neighbor, graph, visited); }); } depthFirstRecur("f", graph); ``` --- #### Dynamic Recursive Example ```js function depthFirst(graph) { let visited = new Set(); for (let node in graph) { _depthFirstRecur(node, graph, visited); } } function _depthFirstRecur(node, graph, visited) { if (visited.has(node)) return; console.log(node); visited.add(node); graph[node].forEach((neighbor) => { _depthFirstRecur(neighbor, graph, visited); }); } depthFirst(graph); ```