graph.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //Link is like an Edge in the graph/tree structure
  2. class Link {
  3. constructor(from, to) {
  4. this.to = to;
  5. this.from = from;
  6. }
  7. }
  8. //Node--> Vertex
  9. class Node {
  10. constructor(id){
  11. this.id = id;
  12. }
  13. }
  14. class Graph{
  15. constructor(){
  16. this.nodes = {};
  17. this.links = {}
  18. }
  19. addNode(node){
  20. if(this.nodes[node.id]){
  21. throw new Error("Node already exists with ID "+node.id);
  22. }
  23. this.nodes[node.id] = node;
  24. if(!this.links[node.id]) this.links[node.id] = this._emptyLink();
  25. }
  26. _emptyLink() {
  27. return {
  28. out: new Set(),
  29. in: new Set()
  30. };
  31. }
  32. //we give the link we
  33. addLink(link){
  34. let from = link.from;
  35. let to = link.to;
  36. if(!this.nodes[from.id] || !this.nodes[to.id]){
  37. throw new Error("One of the Nodes Doesnt Exist");
  38. }
  39. if(this.links[from.id].out.has(link) || this.links[to.id].in.has(link)){
  40. throw new Error("Link already exists");
  41. }
  42. this.links[from.id].out.add(link);
  43. this.links[to.id].in.add(link);
  44. return link;
  45. }
  46. removeLink(link){
  47. this.links[link.from.id].out.delete(link);
  48. this.links[link.to.id].in.delete(link);
  49. }
  50. removeNode(node){
  51. if(!this.nodes[node.id]) return true;
  52. let outlinks = this.links[node.id].out
  53. let inlinks = this.links[node.id].in;
  54. outlinks.forEach( link => this.removeLink(link))
  55. inlinks.forEach( link => this.removeLink(link))
  56. delete this.nodes[node.id];
  57. delete this.links[node.id];
  58. return node;
  59. }
  60. linkNodes(src, dest) {
  61. return this.addLink(new Link(src, dest));
  62. }
  63. has(id) {
  64. return !!this.nodes[id];
  65. }
  66. getNode(id) {
  67. return this.nodes[id];
  68. }
  69. getLinks(nodeid) {
  70. return this.links[nodeid];
  71. }
  72. DFSRecursive(start, cb){
  73. if(!start) return null;
  74. var resultList = [];
  75. var visited = {};
  76. var links = this.links;
  77. var found = false;
  78. (function dfs(vertex){
  79. visited[vertex.id] = true;
  80. resultList.push(vertex);
  81. //console.log(resultList)
  82. if( cb(vertex) === true ) {
  83. //console.log("####true")
  84. found = true;
  85. return resultList;
  86. }
  87. for(var link of links[vertex.id].out) {
  88. if(!visited[link.to.id]){
  89. let res = dfs(link.to);
  90. if(found)return;
  91. resultList.pop();
  92. }
  93. }
  94. })(start)
  95. return resultList;
  96. }
  97. //depth first
  98. DFS(start,cb){
  99. var visited = {};
  100. visited[start.id] = true;
  101. var stack = [start];
  102. var stackRes = [[]];
  103. let vertex;
  104. while(stack.length){
  105. vertex = stack.pop();
  106. let res = stackRes.pop();
  107. // console.log(res);
  108. if( cb(vertex) === true ) {
  109. return [...res, vertex];
  110. }
  111. for( var link of this.links[vertex.id].out ) {
  112. if(!visited[link.to.id]){
  113. visited[link.to.id] = true;
  114. stack.push(link.to);
  115. stackRes.push([...res, vertex]);
  116. }
  117. }
  118. // resultList.pop();
  119. }
  120. return false;
  121. }
  122. BFS(start,cb){
  123. var visited = {[start.id]:true}
  124. var stack = [start];
  125. var stackRes = [[]];
  126. let vertex;
  127. while(stack.length){
  128. vertex = stack.shift();
  129. let res = stackRes.shift();
  130. if( cb(vertex) === true ) {
  131. return [...res, vertex];
  132. }
  133. for( var link of this.links[vertex.id].out ) {
  134. if(!visited[link.to.id]){
  135. visited[link.to.id] = true;
  136. stack.push(link.to);
  137. stackRes.push([...res, vertex]);
  138. }
  139. }
  140. }
  141. return false;
  142. }
  143. _debug(){
  144. }
  145. }
  146. // var graph = new Graph(Node);
  147. // var A = new Node("A");
  148. // var B = new Node('B');
  149. // var C = new Node('C');
  150. // var D = new Node('D');
  151. // var E = new Node('E');
  152. // var F = new Node("F");
  153. // var AB = new Link(A,B);
  154. // var AD = new Link(A,D);
  155. // var BC = new Link(B,C);
  156. // var CF = new Link(C,F);
  157. // var DB = new Link(D,B);
  158. // var DE = new Link(D,E);
  159. // var EF = new Link(E,F);
  160. // var FE = new Link(F,E);
  161. /*
  162. graph.addNode(A);
  163. graph.addNode(B);
  164. graph.addNode(C);
  165. graph.addNode(D);
  166. graph.addNode(E);
  167. graph.addNode(F);
  168. graph.addLink(AB);
  169. graph.addLink(AD);
  170. graph.addLink(BC);
  171. graph.addLink(CF);
  172. graph.addLink(DB);
  173. graph.addLink(DE);
  174. graph.addLink(EF);
  175. graph.addLink(FE);
  176. */
  177. //let recur = graph.DFS(A,(node) => node.id === E.id);
  178. //let bfs = graph.BFS(A,(node) => node.id === C.id);
  179. module.exports = {
  180. Node,
  181. Link,
  182. Graph
  183. };