Advertisement
Guest User

Untitled

a guest
Dec 9th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.33 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "bfs.h"
  5.  
  6.  
  7. int get_neighbors(const Grid *grid, Point p, Point neighb[])
  8. {
  9. // TODO: fill the array neighb with the neighbors of the point p and return the number of neighbors
  10. // the point p will have at most 4 neighbors (up, down, left, right)
  11. // avoid the neighbors that are outside the grid limits or fall into a wall
  12. // note: the size of the array neighb is guaranteed to be at least 4
  13.  
  14. int i = p.row;
  15. int j = p.col;
  16. int c = 0;
  17. if (grid->mat[i][j] == 0)
  18. {
  19. if (grid->mat[i - 1][j] == 0)
  20. {
  21. neighb[c].row = i - 1;
  22. neighb[c].col = j;
  23. c++;
  24. }
  25. if (grid->mat[i + 1][j] == 0)
  26. {
  27. neighb[c].row = i + 1;
  28. neighb[c].col = j;
  29. c++;
  30. }
  31. if (grid->mat[i][j - 1] == 0)
  32. {
  33. neighb[c].row = i;
  34. neighb[c].col = j - 1;
  35. c++;
  36. }
  37. if (grid->mat[i][j + 1] == 0)
  38. {
  39. neighb[c].row = i;
  40. neighb[c].col = j + 1;
  41. c++;
  42. }
  43. }
  44. return c;
  45. }
  46.  
  47. void grid_to_graph(const Grid *grid, Graph *graph)
  48. {
  49. //we need to keep the nodes in a matrix, so we can easily refer to a position in the grid
  50. Node *nodes[MAX_ROWS][MAX_COLS];
  51. int i, j, k;
  52. Point neighb[4];
  53.  
  54. //compute how many nodes we have and allocate each node
  55. graph->nrNodes = 0;
  56. for(i=0; i<grid->rows; ++i){
  57. for(j=0; j<grid->cols; ++j){
  58. if(grid->mat[i][j] == 0){
  59. nodes[i][j] = (Node*)malloc(sizeof(Node));
  60. memset(nodes[i][j], 0, sizeof(Node)); //initialize all fields with 0/NULL
  61. nodes[i][j]->position.row = i;
  62. nodes[i][j]->position.col = j;
  63. ++graph->nrNodes;
  64. }else{
  65. nodes[i][j] = NULL;
  66. }
  67. }
  68. }
  69. graph->v = (Node**)malloc(graph->nrNodes * sizeof(Node*));
  70. k = 0;
  71. for(i=0; i<grid->rows; ++i){
  72. for(j=0; j<grid->cols; ++j){
  73. if(nodes[i][j] != NULL){
  74. graph->v[k++] = nodes[i][j];
  75. }
  76. }
  77. }
  78.  
  79. //compute the adjacency list for each node
  80. for(i=0; i<graph->nrNodes; ++i){
  81. graph->v[i]->adjSize = get_neighbors(grid, graph->v[i]->position, neighb);
  82. if(graph->v[i]->adjSize != 0){
  83. graph->v[i]->adj = (Node**)malloc(graph->v[i]->adjSize * sizeof(Node*));
  84. k = 0;
  85. for(j=0; j<graph->v[i]->adjSize; ++j){
  86. if( neighb[j].row >= 0 && neighb[j].row < grid->rows &&
  87. neighb[j].col >= 0 && neighb[j].col < grid->cols &&
  88. grid->mat[neighb[j].row][neighb[j].col] == 0){
  89. graph->v[i]->adj[k++] = nodes[neighb[j].row][neighb[j].col];
  90. }
  91. }
  92. if(k < graph->v[i]->adjSize){
  93. //get_neighbors returned some invalid neighbors
  94. graph->v[i]->adjSize = k;
  95. graph->v[i]->adj = (Node**)realloc(graph->v[i]->adj, k * sizeof(Node*));
  96. }
  97. }
  98. }
  99. }
  100.  
  101. void free_graph(Graph *graph)
  102. {
  103. if(graph->v != NULL){
  104. for(int i=0; i<graph->nrNodes; ++i){
  105. if(graph->v[i] != NULL){
  106. if(graph->v[i]->adj != NULL){
  107. free(graph->v[i]->adj);
  108. graph->v[i]->adj = NULL;
  109. }
  110. graph->v[i]->adjSize = 0;
  111. free(graph->v[i]);
  112. graph->v[i] = NULL;
  113. }
  114. }
  115. free(graph->v);
  116. graph->v = NULL;
  117. }
  118. graph->nrNodes = 0;
  119. }
  120.  
  121. typedef struct
  122. {
  123. Node* first;
  124. Node* last;
  125. }Queue;
  126.  
  127. void enqueue(Queue* q, Node* s) //insert in queue (at rear)
  128. {
  129. if (q->first == 0)
  130. {
  131. q->first = s;
  132. q->last = s;
  133. q->last->parent = NULL;
  134. }
  135. else
  136. {
  137. s->parent = q->last;
  138. q->last = s;
  139. }
  140. }
  141.  
  142. Node* dequeue(Queue* q) //delete (from front)
  143. {
  144. Node* recuperat = NULL;
  145. Node* prev = NULL;
  146. Node* curr = NULL;
  147. if (q->first != 0)
  148. if (q->last->parent != 0)
  149. {
  150. prev = q->last->parent;
  151. curr = q->last;
  152. while (prev != q->first)
  153. {
  154. curr = prev;
  155. prev = prev->parent;
  156. }
  157. recuperat = prev;
  158. q->first = curr;
  159. curr->parent = NULL;
  160. }
  161. else
  162. {
  163. recuperat = q->first;
  164. q->first = NULL;
  165. }
  166. return recuperat;
  167. }
  168.  
  169. void bfs(Graph *graph, Node *s, Operation *op)
  170. {
  171. // TOOD: implement the BFS algorithm on the graph, starting from the node s
  172. // at the end of the algorithm, every node reachable from s should have the color BLACK
  173. // for all the visited nodes, the minimum distance from s (dist) and the parent in the BFS tree should be set
  174. // for counting the number of operations, the optional op parameter is received
  175. // since op can be NULL (when we are calling the bfs for display purposes), you should check it before counting:
  176. // if(op != NULL) op->count();
  177.  
  178. for (int i = 0; i < graph->nrNodes; i++)
  179. {
  180. graph->v[i]->color = COLOR_WHITE;
  181. graph->v[i]->dist = 0;
  182. graph->v[i]->parent = NULL;
  183. }
  184. s->color = COLOR_GRAY;
  185. s->dist = 0;
  186. s->parent = NULL;
  187. Queue* q = (Queue*)malloc(sizeof(Queue));
  188. q->first = q->last = NULL;
  189. enqueue(q, s);
  190. while (q->first != NULL)
  191. {
  192. Node* u = dequeue(q);
  193. for (int j = 0; j < u->adjSize; j++)
  194. if (u->adj[j]->color == COLOR_WHITE)
  195. {
  196. u->adj[j]->color = COLOR_GRAY;
  197. u->adj[j]->dist = u->dist + 1;
  198. u->adj[j]->parent = u;
  199. enqueue(q, u->adj[j]);
  200. }
  201. u->color = COLOR_BLACK;
  202. }
  203. }
  204.  
  205. void print_bfs_tree(Graph *graph)
  206. {
  207. //first, we will represent the BFS tree as a parent array
  208. int n = 0; //the number of nodes
  209. int *p = NULL; //the parent array
  210. Point *repr = NULL; //the representation for each element in p
  211.  
  212. //some of the nodes in graph->v may not have been reached by BFS
  213. //p and repr will contain only the reachable nodes
  214. int *transf = (int*)malloc(graph->nrNodes * sizeof(int));
  215. for(int i=0; i<graph->nrNodes; ++i){
  216. if(graph->v[i]->color == COLOR_BLACK){
  217. transf[i] = n;
  218. ++n;
  219. }else{
  220. transf[i] = -1;
  221. }
  222. }
  223. if(n == 0){
  224. //no BFS tree
  225. free(transf);
  226. return;
  227. }
  228.  
  229. int err = 0;
  230. p = (int*)malloc(n * sizeof(int));
  231. repr = (Point*)malloc(n * sizeof(Node));
  232. for(int i=0; i<graph->nrNodes && !err; ++i){
  233. if(graph->v[i]->color == COLOR_BLACK){
  234. if(transf[i] < 0 || transf[i] >= n){
  235. err = 1;
  236. }else{
  237. repr[transf[i]] = graph->v[i]->position;
  238. if(graph->v[i]->parent == NULL){
  239. p[transf[i]] = -1;
  240. }else{
  241. err = 1;
  242. for(int j=0; j<graph->nrNodes; ++j){
  243. if(graph->v[i]->parent == graph->v[j]){
  244. if(transf[j] >= 0 && transf[j] < n){
  245. p[transf[i]] = transf[j];
  246. err = 0;
  247. }
  248. break;
  249. }
  250. }
  251. }
  252. }
  253. }
  254. }
  255. free(transf);
  256. transf = NULL;
  257.  
  258. if(!err){
  259. // TODO: pretty print the BFS tree
  260. // the parrent array is p (p[k] is the parent for node k or -1 if k is the root)
  261. // when printing the node k, print repr[k] (it contains the row and column for that point)
  262. // you can adapt the code for transforming and printing multi-way trees from the previous labs
  263.  
  264. }
  265.  
  266. if(p != NULL){
  267. free(p);
  268. p = NULL;
  269. }
  270. if(repr != NULL){
  271. free(repr);
  272. repr = NULL;
  273. }
  274. }
  275.  
  276. int shortest_path(Graph *graph, Node *start, Node *end, Node *path[])
  277. {
  278. // TODO: compute the shortest path between the nodes start and end in the given graph
  279. // the nodes from the path, should be filled, in order, in the array path
  280. // the number of nodes filled in the path array should be returned
  281. // if end is not reachable from start, return -1
  282. // note: the size of the array path is guaranteed to be at least 1000
  283. return -1;
  284. }
  285.  
  286.  
  287. void performance()
  288. {
  289. int n, i;
  290. Profiler p("bfs");
  291.  
  292. // vary the number of edges
  293. for(n=1000; n<=4500; n+=100){
  294. Operation op = p.createOperation("bfs-edges", n);
  295. Graph graph;
  296. graph.nrNodes = 100;
  297. //initialize the nodes of the graph
  298. graph.v = (Node**)malloc(graph.nrNodes * sizeof(Node*));
  299. for(i=0; i<graph.nrNodes; ++i){
  300. graph.v[i] = (Node*)malloc(sizeof(Node));
  301. memset(graph.v[i], 0, sizeof(Node));
  302. }
  303. // TODO: generate n random edges
  304. // make sure the generated graph is connected
  305.  
  306. bfs(&graph, graph.v[0], &op);
  307. free_graph(&graph);
  308. }
  309.  
  310. // vary the number of vertices
  311. for(n=100; n<=200; n+=10){
  312. Operation op = p.createOperation("bfs-vertices", n);
  313. Graph graph;
  314. graph.nrNodes = n;
  315. //initialize the nodes of the graph
  316. graph.v = (Node**)malloc(graph.nrNodes * sizeof(Node*));
  317. for(i=0; i<graph.nrNodes; ++i){
  318. graph.v[i] = (Node*)malloc(sizeof(Node));
  319. memset(graph.v[i], 0, sizeof(Node));
  320. }
  321. // TODO: generate 4500 random edges
  322. // make sure the generated graph is connected
  323.  
  324. bfs(&graph, graph.v[0], &op);
  325. free_graph(&graph);
  326. }
  327.  
  328. p.showReport();
  329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement