当前位置:   article > 正文

找出无向图中所有的环的算法_无向图找环

无向图找环

本文给出了一个找到无向图中所有的环的递归算法,该算法是基于DFS(深度优先搜索)的,大概的思路是:在深度优先搜索无向图的过程中,当遇到起始点的时候,会认定为出现环(在本文中只是找出了无向图中所有的长度大于等于3的环(长度为1和2的环没有意思),所以在深搜的过程中,当遇到的是起始点的时候,还需要进行判断是否是环),当确定是出现了环之后,根据是否在遇到环之前的那个点还有其他的路径,来决定是进一步的进行深度优先搜索还是进行回退,在进行深度优先搜索的过程中,将访问过的节点标记,若当前的节点无路可走(不能进行深度优先搜索了),在回退的过程中,将标记取消。算法的过程就下图做简单的介绍:


假设以1为起点进行深度优先搜索,经过访问2,3,4,5,6会得到一个环,因为节点6还有下一条路径可走,此时程序会进入7,8,9,10这些点进行深度优先搜索,但是都再没有回到节点1,于是程序会一层一层的在从7,8,9,10(不一定是这样的顺序)这些点退出来。退至节点6,5,4直到3节点(将6,5,4的标记全部取消)找到了下一条路径5,在走到6,此时又发现了另一条环1->2->3->5->6->1.以此类推。

主要代码如下:

  1. <span style="font-family:Courier New;font-size:12px;">void DFS(int startVertax)
  2. {
  3. setVisitedFlag(startVertax, 1);
  4. int nextVertax;
  5. push_stack(&loop_stack, startVertax);
  6. nextVertax = firstAdjacentVertax(startVertax);
  7. innerStep++;
  8. for( ; ; )
  9. {
  10. if( nextVertax != -1 )
  11. {
  12. if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep == 2 ) //从1到2,又从2到1,这不算是一个环
  13. {
  14. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  15. continue;
  16. }
  17. else if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep != 2 ) //找到了一个环
  18. {
  19. printf("loop length: %d\t", innerStep);
  20. print_stack(loop_stack);
  21. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  22. continue;
  23. }
  24. else if( visitedFlag[nextVertax] == 0 )<span style="white-space:pre"> </span>//进行递归
  25. {
  26. DFS(nextVertax);
  27. }
  28. if( isRecall == 1 ) //进行回退
  29. {
  30. innerStep--;
  31. temp = nextVertax;
  32. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  33. pop_stack(&loop_stack, &pop_value);
  34. setVisitedFlag(temp, 0);
  35. isRecall = 0;
  36. continue;
  37. }
  38. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  39. }
  40. else if( nextVertax == -1 )
  41. {
  42. isRecall = 1;
  43. break;
  44. }
  45. }
  46. }
  47. void DFSTraverse()
  48. {
  49. initialVisitedFlagArray();
  50. initializeSequenceStack(&loop_stack);
  51. int i;
  52. for( heap = 1; heap <= vertax_size; heap++ )
  53. {
  54. for( i = 1; i <= vertax_size; i++ )
  55. {
  56. visitedFlag[i] = 0;
  57. }
  58. /*
  59. printf("print the visitedFlag array: ");
  60. for( i = 1; i <= vertax_size; i++ )
  61. {
  62. printf("%d ", visitedFlag[i]);
  63. }
  64. printf("\n");
  65. */
  66. if( visitedFlag[heap] == 0 )
  67. {
  68. printf("\n-------------------the loop start and end with %d----------------\n", heap);
  69. clear_stack(&loop_stack);
  70. innerStep = 0;
  71. isRecall = 0;
  72. DFS(heap);
  73. }
  74. }
  75. }</span>

对于上图的程序的运行结果为:(需要注意的是:对于无向图中的每一条环会出现两次,因为是有方向的:顺时针和逆时针)。






完整代码

  1. <span style="font-family:Courier New;">#include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<math.h>
  5. int eage_size;
  6. int vertax_size;
  7. char filename_eage[200];
  8. char filename_vertax[200];
  9. int** eage_set;
  10. char** vertax_set;
  11. int** adjacentMatrix;
  12. int* visitedFlag;
  13. typedef struct SequenceStack
  14. {
  15. int* base;
  16. int* top;
  17. int stackSize;
  18. }SequenceStack;
  19. void readEageDataFromFile();
  20. void readVertaxDataFromFile();
  21. void createAdjacentMatrix();
  22. void DFS(int);
  23. void DFSTraverse();
  24. void initialVisitedFlagArray();
  25. void printVisitedVertax(int);
  26. void setVisitedFlag(int,int);
  27. int firstAdjacentVertax(int);
  28. int nextAdjacentVertax(int,int);
  29. void initializeSequenceStack(SequenceStack*);
  30. void pop_stack(SequenceStack*, int*);
  31. void push_stack(SequenceStack*, int);
  32. void print_stack(SequenceStack);
  33. int empty_stack(SequenceStack);
  34. void clear_stack(SequenceStack*);
  35. void test_stack();
  36. int main(int argc, char* argv[])
  37. {
  38. if( argc != 5 )
  39. {
  40. printf("\tThis algorithm require 3 parameters"
  41. "\n\t\t1:the size of eage"
  42. "\n\t\t2:the filename contain eage-data"
  43. "\n\t\t3:the size of vertax"
  44. "\n\t\t4:the filename contain vertax-data");
  45. exit(0);
  46. }
  47. eage_size = atoi(argv[1]);
  48. strcat(filename_eage, argv[2]);
  49. vertax_size = atoi(argv[3]);
  50. strcat(filename_vertax, argv[4]);
  51. printf("eage_size : %d, vertax_size : %d, filename-eage : %s, filename-vertax : %s\n", eage_size, vertax_size, filename_eage, filename_vertax);
  52. readEageDataFromFile();
  53. readVertaxDataFromFile();
  54. createAdjacentMatrix();
  55. DFSTraverse();
  56. //test_stack();
  57. return 0;
  58. }
  59. void readEageDataFromFile()
  60. {
  61. FILE* f_read;
  62. if( NULL == (f_read = fopen(filename_eage, "r")))
  63. {
  64. printf("open file(%s) error!\n", filename_eage);
  65. exit(0);
  66. }
  67. //create dynamic array for storing original data form file @filename
  68. eage_set = (int**)malloc(sizeof(int*) * (eage_size + 1));
  69. if( !eage_set )
  70. {
  71. printf("malloc error: eage_set**\n");
  72. exit(0);
  73. }
  74. int i;
  75. for( i = 1; i <= eage_size; i++ )
  76. {
  77. eage_set[i] = (int*)malloc(sizeof(int) * (2 + 1));
  78. if( !eage_set[i] )
  79. {
  80. printf("eage_set[%d] malloc error", i);
  81. exit(0);
  82. }
  83. }
  84. //read original data from file
  85. for( i = 1; i <= eage_size; i++ )
  86. {
  87. if( 2 != fscanf(f_read, "%d %d", &eage_set[i][1], &eage_set[i][2]))
  88. {
  89. printf("fscanf error: %d\n", i);
  90. exit(0);
  91. }
  92. }
  93. //test
  94. printf("\n show the origin data from file\n");
  95. for( i = 1; i <= eage_size; i++ )
  96. {
  97. printf("%d\t%d\n", eage_set[i][1], eage_set[i][2]);
  98. }
  99. printf("\n");
  100. //test END
  101. }
  102. void readVertaxDataFromFile()
  103. {
  104. //create the dynamic array for saving vertax-set information
  105. vertax_set = (char**)malloc(sizeof(char*) * (vertax_size + 1));
  106. if( !vertax_set )
  107. {
  108. printf("vertax_set malloc error");
  109. exit(0);
  110. }
  111. int i;
  112. for( i = 1; i <= vertax_size; i++ )
  113. {
  114. vertax_set[i] = (char*)malloc(sizeof(char) * (20 + 1));
  115. if( !vertax_set[i] )
  116. {
  117. printf("vertax_set[%d] malloc error");
  118. exit(0);
  119. }
  120. }
  121. //open file
  122. FILE* f_read;
  123. if( NULL == (f_read = fopen(filename_vertax, "r")))
  124. {
  125. printf("open file(%s) error", filename_vertax);
  126. exit(0);
  127. }
  128. //read vertax-set information
  129. for( i = 1; i <= vertax_size; i++ )
  130. {
  131. if( 1 != fscanf(f_read, "%s ", vertax_set[i]) )
  132. {
  133. printf("fscanf vertax_set[%d] error", i);
  134. exit(0);
  135. }
  136. }
  137. //test
  138. for( i = 1; i <= vertax_size; i++ )
  139. {
  140. printf("%s\n", vertax_set[i]);
  141. }
  142. printf("\n");
  143. //test END
  144. }
  145. void createAdjacentMatrix()
  146. {
  147. //create the dynamic array for saving adjcaent matrix
  148. adjacentMatrix = (int**)malloc(sizeof(int*) * (vertax_size + 1));
  149. if( !adjacentMatrix )
  150. {
  151. printf("adjacentMatrix** malloc error");
  152. exit(0);
  153. }
  154. int i;
  155. for( i = 1; i <= vertax_size; i++ )
  156. {
  157. adjacentMatrix[i] = (int*)malloc(sizeof(int) * (vertax_size + 1));
  158. if( !adjacentMatrix[i] )
  159. {
  160. printf("adjacentMatrix[%d] malloc error");
  161. exit(0);
  162. }
  163. }
  164. //initial the value of adjacentMatrix
  165. int j;
  166. for( i = 1; i <= vertax_size; i++ )
  167. {
  168. for( j = 1; j <= vertax_size; j++ )
  169. {
  170. adjacentMatrix[i][j] = 0;
  171. }
  172. }
  173. //set the value for adjacentMatrix
  174. for( i = 1; i <= eage_size; i++ )
  175. {
  176. adjacentMatrix[eage_set[i][1]][eage_set[i][2]] = 1;
  177. adjacentMatrix[eage_set[i][2]][eage_set[i][1]] = 1;
  178. }
  179. //test
  180. printf("\n show the information about adjacent matrix: \n");
  181. for( i = 1; i <= vertax_size; i++ )
  182. {
  183. for( j = 1; j <= vertax_size; j++ )
  184. {
  185. printf("%d ", adjacentMatrix[i][j]);
  186. }
  187. printf("\n");
  188. }
  189. //test END
  190. }
  191. int loop_count;
  192. int heap;
  193. int innerStep = 0;
  194. int temp;
  195. int isRecall;
  196. SequenceStack loop_stack;
  197. int pop_value;
  198. void DFS(int startVertax)
  199. {
  200. setVisitedFlag(startVertax, 1);
  201. int nextVertax;
  202. push_stack(&loop_stack, startVertax);
  203. nextVertax = firstAdjacentVertax(startVertax);
  204. innerStep++;
  205. for( ; ; )
  206. {
  207. if( nextVertax != -1 )
  208. {
  209. if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep == 2 )
  210. {
  211. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  212. continue;
  213. }
  214. else if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep != 2 )
  215. {
  216. print_stack(loop_stack);
  217. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  218. continue;
  219. }
  220. else if( visitedFlag[nextVertax] == 0 )
  221. {
  222. DFS(nextVertax);
  223. }
  224. if( isRecall == 1 )
  225. {
  226. innerStep--;
  227. temp = nextVertax;
  228. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  229. pop_stack(&loop_stack, &pop_value);
  230. setVisitedFlag(temp, 0);
  231. isRecall = 0;
  232. continue;
  233. }
  234. nextVertax = nextAdjacentVertax(startVertax, nextVertax);
  235. }
  236. else if( nextVertax == -1 )
  237. {
  238. isRecall = 1;
  239. break;
  240. }
  241. }
  242. }
  243. void DFSTraverse()
  244. {
  245. initialVisitedFlagArray();
  246. initializeSequenceStack(&loop_stack);
  247. int i;
  248. for( heap = 1; heap <= vertax_size; heap++ )
  249. {
  250. for( i = 1; i <= vertax_size; i++ )
  251. {
  252. visitedFlag[i] = 0;
  253. }
  254. /*
  255. printf("print the visitedFlag array: ");
  256. for( i = 1; i <= vertax_size; i++ )
  257. {
  258. printf("%d ", visitedFlag[i]);
  259. }
  260. printf("\n");
  261. */
  262. if( visitedFlag[heap] == 0 )
  263. {
  264. printf("\n-------------------the loop start and end with %d----------------\n", heap);
  265. clear_stack(&loop_stack);
  266. innerStep = 0;
  267. //printf("isRecall : %d, findLoop : %d, hasOthers : %d\n", isRecall, findLoop, hasOthers);
  268. isRecall = 0;
  269. DFS(heap);
  270. }
  271. }
  272. }
  273. void initialVisitedFlagArray()
  274. {
  275. visitedFlag = (int*)malloc(sizeof(int) * (vertax_size + 1));
  276. if( !visitedFlag )
  277. {
  278. printf("visitedFlag* malloc error");
  279. exit(0);
  280. }
  281. int i;
  282. for( i = 1; i <= vertax_size; i++ )
  283. visitedFlag[i] = 0;
  284. }
  285. void printVisitedVertax(int vertaxID)
  286. {
  287. printf("visited: %d \n", vertaxID);
  288. }
  289. void setVisitedFlag(int vertaxID, int value)
  290. {
  291. visitedFlag[vertaxID] = value;
  292. }
  293. int firstAdjacentVertax(int vertaxID)
  294. {
  295. int i;
  296. for( i = 1; i <= vertax_size; i++ )
  297. {
  298. if( adjacentMatrix[vertaxID][i] == 1 )
  299. return i;
  300. }
  301. return -1;
  302. }
  303. int nextAdjacentVertax(int vertaxID, int nextVertaxID)
  304. {
  305. int i;
  306. for( i = nextVertaxID + 1; i <= vertax_size; i++ )
  307. {
  308. if( adjacentMatrix[vertaxID][i] == 1 )
  309. return i;
  310. }
  311. return -1;
  312. }
  313. void initializeSequenceStack(SequenceStack* stack)
  314. {
  315. stack->base = (int*)malloc(sizeof(int) * (vertax_size + 1));
  316. if( !stack->base )
  317. {
  318. printf("Sequence stack malloc error!\n");
  319. exit(0);
  320. }
  321. stack->top = stack->base;
  322. stack->stackSize = vertax_size;
  323. }
  324. void pop_stack(SequenceStack* stack, int* value)
  325. {
  326. if( empty_stack(*stack) == 1 )
  327. {
  328. printf("stack is empty , can not to pop!\n");
  329. exit(0);
  330. }
  331. *value = *(--(stack->top));
  332. }
  333. void push_stack(SequenceStack* stack, int value)
  334. {
  335. *(stack->top) = value;
  336. (stack->top)++;
  337. }
  338. int empty_stack(SequenceStack stack)
  339. {
  340. return stack.top == stack.base ? 1 : 0;
  341. }
  342. void print_stack(SequenceStack stack)
  343. {
  344. int temp = *(stack.base);
  345. while( stack.top != stack.base )
  346. {
  347. printf("%d->", *((stack.base)++));
  348. }
  349. printf("%d\n", temp);
  350. }
  351. void clear_stack(SequenceStack* stack)
  352. {
  353. stack->top = stack->base;
  354. }</span>


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/64539
推荐阅读
相关标签
  

闽ICP备14008679号