graph.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //Link is like an Edge in the graph/tree structure
  2. class Link {
  3. constructor(src, dest) {
  4. this.to = dest;
  5. this.from = src;
  6. }
  7. import(data) {
  8. for(var i in data) {
  9. this[i] = data[i];
  10. }
  11. return this;
  12. }
  13. export() {
  14. return this;
  15. }
  16. }
  17. //Node--> Vertex
  18. class Node {
  19. constructor(id){
  20. this.id = id;
  21. }
  22. import(data) {
  23. for(var i in data) {
  24. this[i] = data[i];
  25. }
  26. return this;
  27. }
  28. export() {
  29. return this;
  30. }
  31. }
  32. class Graph{
  33. constructor(){
  34. this.nodes = {};
  35. this.links = {}
  36. }
  37. addNode(node){
  38. if(this.nodes[node.id]){
  39. throw new Error("Node already exists with ID "+node.id);
  40. }
  41. this.nodes[node.id] = node;
  42. if(!this.links[node.id]) this.links[node.id] = this._emptyLink();
  43. }
  44. _emptyLink() {
  45. return {
  46. out: new Set(),
  47. in: new Set()
  48. };
  49. }
  50. //we give the link we
  51. addLink(link){
  52. let dest = link.from;
  53. let to = link.to;
  54. if(!this.nodes[dest] || !this.nodes[to]){
  55. console.log(this.nodes, dest, to);
  56. throw new Error("One of the Nodes Doesnt Exist");
  57. }
  58. if(this.links[dest].out.has(link) || this.links[to].in.has(link)){
  59. throw new Error("Link already exists");
  60. }
  61. this.links[dest].out.add(link);
  62. this.links[to].in.add(link);
  63. return link;
  64. }
  65. removeLink(link){
  66. this.links[link.from].out.delete(link);
  67. this.links[link.to].in.delete(link);
  68. }
  69. removeNode(node){
  70. if(!this.nodes[node.id]) return true;
  71. let outlinks = this.links[node.id].out
  72. let inlinks = this.links[node.id].in;
  73. outlinks.forEach(link => this.removeLink(link))
  74. inlinks.forEach(link => this.removeLink(link))
  75. delete this.nodes[node.id];
  76. delete this.links[node.id];
  77. return node;
  78. }
  79. linkNodes(src, dest) {
  80. return this.addLink(new Link(src, dest));
  81. }
  82. has(id) {
  83. return !!this.nodes[id];
  84. }
  85. getNode(id) {
  86. return this.nodes[id];
  87. }
  88. getLinks(nodeid) {
  89. return this.links[nodeid];
  90. }
  91. DFSRecursive(start, cb){ // needs correction because of link change to id
  92. if(!start) return null;
  93. var resultList = [];
  94. var visited = {};
  95. var links = this.links;
  96. var found = false;
  97. let self = this;
  98. (function dfs(vertex){
  99. visited[vertex.id] = true;
  100. resultList.push(vertex);
  101. if( cb(vertex) === true ) {
  102. found = true;
  103. return resultList;
  104. }
  105. for(var link of links[vertex.id].out) {
  106. let destNode = self.getNode(link.to);
  107. if(!visited[destNode]){
  108. let res = dfs(destNode);
  109. if(found)return;
  110. resultList.pop();
  111. }
  112. }
  113. })(start)
  114. return resultList;
  115. }
  116. //depth first
  117. DFS(start,cb){ // needs correction because of link change to id
  118. var visited = {};
  119. visited[start.id] = true;
  120. var stack = [start];
  121. var stackRes = [[]];
  122. let vertex;
  123. while(stack.length){
  124. vertex = stack.pop();
  125. let res = stackRes.pop();
  126. if( cb(vertex) === true ) {
  127. return [...res, vertex];
  128. }
  129. for( var link of this.links[vertex.id].out ) {
  130. let destNode = link.to;
  131. if(!visited[destNode]){
  132. visited[destNode] = true;
  133. stack.push(link.to);
  134. stackRes.push([...res, vertex]);
  135. }
  136. }
  137. // resultList.pop();
  138. }
  139. return false;
  140. }
  141. BFS(start,cb){ // needs correction because of link change to id
  142. var visited = {[start.id]:true}
  143. var stack = [start];
  144. var stackRes = [[]];
  145. let vertex;
  146. while(stack.length){
  147. vertex = stack.shift();
  148. let res = stackRes.shift();
  149. if( cb(vertex) === true ) {
  150. return [...res, vertex];
  151. }
  152. for( var link of this.links[vertex.id].out ) {
  153. if(!visited[link.to]){
  154. visited[link.to] = true;
  155. stack.push(link.to);
  156. stackRes.push([...res, vertex]);
  157. }
  158. }
  159. }
  160. return false;
  161. }
  162. export() {
  163. let { nodes, links } = this;
  164. // export Links care with SETS
  165. let ln = {};
  166. for(let i in links) {
  167. ln[i] = {
  168. out: Array.from(links[i].out).map(link => link.export()),
  169. in : Array.from(links[i].in ).map(link => link.export())
  170. }
  171. }
  172. // export nodes
  173. let nod = {};
  174. for(let i in nodes) {
  175. nod[i] = nodes[i].export()
  176. }
  177. return {
  178. nodes: nod,
  179. links: ln
  180. };
  181. }
  182. _loadLink(item) {
  183. if(!this.cacheSet) this.cacheSet = {};
  184. let data = this.cacheSet["from" + item.from + "to" + item.to];
  185. if(data) {
  186. return data;
  187. } else {
  188. return this.cacheSet["from" + item.from + "to" + item.to] = new Link().import(item);
  189. }
  190. }
  191. import(data, nodeType = Node) {
  192. let { nodes, links } = data;
  193. for (let i in nodes) {
  194. this.nodes[i] = new nodeType().import(nodes[i]);
  195. }
  196. for (let i in links) {
  197. this.links[i] = {
  198. out: new Set(links[i].out.map(item => this._loadLink(item))),
  199. in : new Set(links[i].in.map(item => this._loadLink(item)))
  200. }
  201. }
  202. }
  203. _debug(){
  204. }
  205. }
  206. // var graph = new Graph(Node);
  207. // var A = new Node("A");
  208. // var B = new Node('B');
  209. // var C = new Node('C');
  210. // var D = new Node('D');
  211. // var E = new Node('E');
  212. // var F = new Node("F");
  213. // var AB = new Link(A,B);
  214. // var AD = new Link(A,D);
  215. // var BC = new Link(B,C);
  216. // var CF = new Link(C,F);
  217. // var DB = new Link(D,B);
  218. // var DE = new Link(D,E);
  219. // var EF = new Link(E,F);
  220. // var FE = new Link(F,E);
  221. /*
  222. graph.addNode(A);
  223. graph.addNode(B);
  224. graph.addNode(C);
  225. graph.addNode(D);
  226. graph.addNode(E);
  227. graph.addNode(F);
  228. graph.addLink(AB);
  229. graph.addLink(AD);
  230. graph.addLink(BC);
  231. graph.addLink(CF);
  232. graph.addLink(DB);
  233. graph.addLink(DE);
  234. graph.addLink(EF);
  235. graph.addLink(FE);
  236. */
  237. //let recur = graph.DFS(A,(node) => node.id === E.id);
  238. //let bfs = graph.BFS(A,(node) => node.id === C.id);
  239. module.exports = {
  240. Node,
  241. Link,
  242. Graph
  243. };