graph.js 5.3 KB

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