GraphService.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package com.example.data_structure.service;
  2. import com.example.data_structure.domain.UDUWGraph;
  3. import com.example.data_structure.domain.UDWGraph;
  4. import com.example.data_structure.vo.GraphTraversalStep;
  5. import com.example.data_structure.vo.GraphTraversalVO;
  6. import com.example.data_structure.vo.PrimMinimumSpanningTree;
  7. import org.springframework.stereotype.Service;
  8. import java.util.*;
  9. @Service
  10. public class GraphService {
  11. private static final int NODE_NUM=7;
  12. //获取一个新的无向非带权图
  13. public UDUWGraph getNewUDUDGraph(){
  14. ArrayList<ArrayList<Integer>> content=new ArrayList<ArrayList<Integer>>();
  15. for(int i=0;i<NODE_NUM;i++){
  16. ArrayList<Integer> raw=new ArrayList<Integer>();
  17. for(int j=0;j<NODE_NUM;j++){
  18. raw.add(0);
  19. }
  20. content.add(raw);
  21. }
  22. //11-21 0.7
  23. int tokeTimes = Math.round(((float)Math.random())*10)+11;
  24. int edgeNum=0;
  25. for(int i=1;i<=tokeTimes;i++){
  26. int left=Math.round(((float)Math.random())*7);
  27. int right=Math.round(((float)Math.random())*7);
  28. while(left==right){
  29. right=Math.round(((float)Math.random())*7);
  30. }
  31. if(content.get(left).get(right)==1){
  32. i--;
  33. }else if(content.get(left).get(right)==0){
  34. content.get(left).set(right,1);
  35. content.get(right).set(left,1);
  36. edgeNum++;
  37. }
  38. }
  39. return new UDUWGraph(content);
  40. }
  41. //获取一个新的无向带权图
  42. public UDWGraph getNewUDWGraph(){
  43. ArrayList<ArrayList<Integer>> content=new ArrayList<ArrayList<Integer>>();
  44. for(int i=0;i<NODE_NUM;i++){
  45. ArrayList<Integer> raw=new ArrayList<Integer>();
  46. for(int j=0;j<NODE_NUM;j++){
  47. raw.add(0);
  48. }
  49. content.add(raw);
  50. }
  51. //11-21 0.7
  52. int tokeTimes = Math.round(((float)Math.random())*10)+11;
  53. int edgeNum=0;
  54. for(int i=1;i<=tokeTimes;i++){
  55. int left=Math.round(((float)Math.random())*7);
  56. int right=Math.round(((float)Math.random())*7);
  57. while(left==right){
  58. right=Math.round(((float)Math.random())*7);
  59. }
  60. if(content.get(left).get(right)==1){
  61. i--;
  62. }else if(content.get(left).get(right)==0){
  63. int weight=Math.round(((float)Math.random())*10);
  64. content.get(left).set(right,weight);
  65. content.get(right).set(left,weight);
  66. edgeNum++;
  67. }
  68. }
  69. return new UDWGraph(content);
  70. }
  71. //获取无向非带权图的广度优先遍历
  72. public GraphTraversalVO getBreadthFirstTraversal(UDUWGraph graph,int startVertex){
  73. ArrayList<ArrayList<Integer>> content=graph.getContent();
  74. ArrayList<Integer> visitSequence =new ArrayList<Integer>();
  75. ArrayList<Integer> visited=new ArrayList<Integer>();
  76. ArrayList<Integer> visitStartNode=new ArrayList<Integer>();
  77. for(int i=0;i<content.size();i++){
  78. System.out.println("=================add===============");
  79. visitStartNode.add(-1);
  80. }
  81. //访问某节点的起初节点
  82. visitStartNode.set(startVertex,startVertex);
  83. GraphTraversalVO graphTraversalVO=new GraphTraversalVO();
  84. graphTraversalVO.setGraph(graph);
  85. ArrayList<GraphTraversalStep> steps=new ArrayList<GraphTraversalStep>();
  86. for(int i=0;i<graph.getNodeNum();i++){
  87. visited.add(0);
  88. }
  89. Queue<Integer> q=new LinkedList<Integer>();
  90. q.add(startVertex);
  91. while(!q.isEmpty()){
  92. int curVertex=q.poll();
  93. steps.add(new GraphTraversalStep("visit",visitStartNode.get(curVertex),curVertex,true));
  94. visited.set(curVertex,1);
  95. visitSequence.add(curVertex);
  96. for(int i=0;i<graph.getNodeNum();i++){
  97. if(content.get(curVertex).get(i)==1){
  98. //如果节点没有被访问,且没有被纳入队列当中,则tryRoad为true
  99. if(visited.get(i)==0&&!q.contains(i)) {
  100. steps.add(new GraphTraversalStep("tryRoad",curVertex,i,true));
  101. if(visitStartNode.get(i)==-1){
  102. visitStartNode.set(i,curVertex);
  103. }
  104. q.offer(i);
  105. }else{
  106. steps.add(new GraphTraversalStep("tryRoad",curVertex,i,false));
  107. }
  108. }
  109. }
  110. }
  111. graphTraversalVO.setContent(steps);
  112. return graphTraversalVO;
  113. }
  114. //获取无向非带权图的深度优先遍历
  115. public GraphTraversalVO getDepthFirstTraversal(UDUWGraph graph,int startVertex){
  116. int nodeNum=graph.getNodeNum();
  117. ArrayList<ArrayList<Integer>> content=graph.getContent();
  118. GraphTraversalVO graphTraversalVO =new GraphTraversalVO();
  119. graphTraversalVO.setGraph(graph);
  120. ArrayList<GraphTraversalStep> steps=new ArrayList<GraphTraversalStep>();
  121. GraphTraversalStep currentStep=new GraphTraversalStep();
  122. ArrayList<Integer> visitSequence=new ArrayList<Integer>();
  123. ArrayList<Integer> visited=new ArrayList<Integer>();
  124. ArrayList<Integer> visitStartNode=new ArrayList<Integer>();
  125. for(int i=0;i<nodeNum;i++){
  126. visited.add(0);
  127. }
  128. for(int i=0;i<nodeNum;i++){
  129. visitStartNode.add(-1);
  130. }
  131. visitStartNode.set(startVertex,startVertex);
  132. Stack<Integer> stack=new Stack<Integer>();
  133. stack.push(startVertex);
  134. visited.set(startVertex,1);
  135. visitSequence.add(startVertex);
  136. steps.add(new GraphTraversalStep("visit",startVertex,startVertex,true));
  137. boolean isTerminal=false;
  138. int formerNode=0;
  139. while(!stack.isEmpty()){
  140. int curVertex=stack.peek();
  141. int nextNode=0;
  142. if(visitSequence.get(visitSequence.size()-1)==curVertex) { //如果正在遍历某支路,没有折返
  143. isTerminal=true;
  144. for (int i = 0; i < nodeNum; i++) {
  145. if (content.get(curVertex).get(i) == 1) {
  146. if (visited.get(i) == 0) {
  147. steps.add(new GraphTraversalStep("tryRoad",curVertex,i,true));
  148. nextNode = i;
  149. steps.add(new GraphTraversalStep("visit",curVertex,i,true));
  150. visited.set(nextNode, 1);
  151. visitSequence.add(nextNode);
  152. stack.push(nextNode);
  153. isTerminal = false;
  154. break;
  155. }else{
  156. steps.add(new GraphTraversalStep("tryRoad",curVertex,i,false));
  157. }
  158. }
  159. }
  160. if(isTerminal){
  161. formerNode=stack.pop();
  162. steps.add(new GraphTraversalStep("return",curVertex,stack.peek(),true));
  163. }
  164. }else{ //如果在折返状态中
  165. if(formerNode<nodeNum-1) {
  166. boolean needReturn=true;
  167. for (int i = formerNode + 1; i < nodeNum; i++) {
  168. if(content.get(curVertex).get(i)==1) {
  169. if (visited.get(i) == 0) {
  170. steps.add(new GraphTraversalStep("tryRoad",curVertex,i,true));
  171. steps.add(new GraphTraversalStep("visit",curVertex,i,true));
  172. stack.push(i);
  173. visited.set(i, 1);
  174. visitSequence.add(i);
  175. needReturn = false;
  176. break;
  177. }else{
  178. steps.add(new GraphTraversalStep("tryRoad",curVertex,i,false));
  179. }
  180. }
  181. }
  182. if(needReturn){
  183. formerNode=stack.pop();
  184. if(!stack.isEmpty()) {
  185. steps.add(new GraphTraversalStep("return", curVertex, stack.peek(), true));
  186. }
  187. }
  188. }else{ //如果当前分支就是最大分支了,则不用探路直接折返
  189. formerNode=stack.pop();
  190. steps.add(new GraphTraversalStep("return",curVertex,stack.peek(),true));
  191. }
  192. }
  193. }
  194. graphTraversalVO.setContent(steps);
  195. return graphTraversalVO;
  196. }
  197. //获取无向带权图的prim算法的最小生成树
  198. public PrimMinimumSpanningTree getPrimMinimumSpanningTree(UDWGraph graph,int startVertex){
  199. ArrayList<ArrayList<Integer>> content=graph.getContent();
  200. int nodeNum=content.size();
  201. ArrayList<Integer> cost=new ArrayList<Integer>();
  202. ArrayList<Boolean> known=new ArrayList<Boolean>();
  203. ArrayList<Integer> startNode=new ArrayList<Integer>();
  204. ArrayList<ArrayList<Integer>> treeEdges=new ArrayList<ArrayList<Integer>>();
  205. ArrayList<Integer> knownSequence=new ArrayList<Integer>();
  206. ArrayList<GraphTraversalStep> steps=new ArrayList<GraphTraversalStep>();
  207. PrimMinimumSpanningTree primMinimumSpanningTree=new PrimMinimumSpanningTree();
  208. for(int i=0;i<nodeNum;i++){
  209. cost.add(Integer.MAX_VALUE);
  210. known.add(false);
  211. startNode.add(-1);
  212. }
  213. cost.set(startVertex,0);
  214. while(knownSequence.size()<nodeNum){ //还有节点没有被连接
  215. int min=Integer.MAX_VALUE;
  216. int indexOfMin=-1;
  217. for(int i=0;i<nodeNum;i++){
  218. if(known.get(i)==false){ //在没有被连接的节点中选一个代价最小的节点
  219. if(cost.get(i)<min){
  220. indexOfMin=i;
  221. min=cost.get(i);
  222. }
  223. }
  224. }
  225. steps.add(new GraphTraversalStep("selectMin",indexOfMin,-1,true));
  226. steps.add(new GraphTraversalStep("setKnown",indexOfMin,-1,true));
  227. known.set(indexOfMin,true); //连接这个节点,并遍历它周围的节点,若代价更小,则将代价和前驱节点替换
  228. knownSequence.add(indexOfMin);
  229. for(int i=0;i<nodeNum;i++){
  230. if(content.get(indexOfMin).get(i)>0){ //如果有边可以到达的话
  231. steps.add(new GraphTraversalStep("tryRoad",indexOfMin,i,true));
  232. if(content.get(indexOfMin).get(i)<cost.get(i)){ //如果代价更小,需要替换
  233. cost.set(i,content.get(indexOfMin).get(i));
  234. startNode.set(i,indexOfMin);
  235. }
  236. }
  237. }
  238. }
  239. for(int i=0;i<nodeNum;i++){
  240. if(i!=startVertex){
  241. ArrayList<Integer> edge=new ArrayList<Integer>();
  242. edge.add(startNode.get(i));
  243. edge.add(i);
  244. treeEdges.add(edge);
  245. }
  246. }
  247. primMinimumSpanningTree.setSteps(steps);
  248. primMinimumSpanningTree.setTreeEdges(treeEdges);
  249. return primMinimumSpanningTree;
  250. }
  251. }