Guest User

Untitled

a guest
May 12th, 2023
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.83 KB | None | 0 0
  1. #include "graph.h"
  2.  
  3.  
  4. /* This function initializes an adjacency list for a graph.
  5.    input parameters:
  6.        The following are 'consumed' by this function
  7.        int           rows   # of rows (or vertices)
  8.  
  9.        The following are 'produced' by this function
  10.        adj_node_t*** list   initialized linked list of adjacencies for each
  11.                 vertex
  12.    return parameters:
  13.        none
  14.  */
  15. void init_adj_list(adj_node_t*** list, int rows)
  16. {
  17.     // Allocate memory
  18.     adj_node_t** tmpList = (adj_node_t**) malloc(sizeof(adj_node_t*) * rows);
  19.     assert(tmpList);
  20.  
  21.     // Initialize each list to point to NULL
  22.     for(int i = 0; i < rows; i++) {
  23.         tmpList[i] = NULL;
  24.     }
  25.  
  26.     // Return list
  27.     *list = tmpList;
  28. }
  29.  
  30.  
  31. /* This function creates a new adj_node_t node for a vertex and initializes
  32.     it with node->vid = vid and node->next = NULL (i.e., no neighbor)
  33.    The function then returns this node
  34.    input parameters:
  35.        int        vid       the ID of the vertex
  36.    return parameters:
  37.        adj_node_t newNode   the new node for the vertex
  38.  */
  39. adj_node_t* create_node(int vid)
  40. {
  41.     adj_node_t* newNode = (adj_node_t*) malloc(sizeof(adj_node_t));
  42.     assert(newNode);
  43.     newNode->vid = vid;
  44.     newNode->next = NULL;
  45.     return newNode;
  46.  
  47. }
  48.  
  49.  
  50. /* Pass in a linked list that represents an adjacnecy list and the row (or
  51.    vertex) to which you need to add a new node.
  52.    First check that the adjacency list for the current row is not
  53.    empty (i.e., NULL). If it is NULL, this is the first adjacent node.
  54.    Otherwise, traverse the list until you reach the end, and then add
  55.    the new node.
  56.    input parameters:
  57.        adj_node_t** list    adjacency list for the current graph
  58.        int          row     vertex that has this node as adjacent
  59.        adj_node_t*  node    the node that needs to be added
  60.    return parameters:
  61.        none
  62.  */
  63. void add_node(adj_node_t** list, int row, adj_node_t* node)
  64. {
  65.     if(list[row] == NULL) {
  66.         // empty list - the head points to this node
  67.         list[row] = node;
  68.     } else {
  69.         // otherwise, find the end, and add it to the end
  70.         adj_node_t* next = list[row];
  71.         while(next->next != NULL) {
  72.             next = next->next;
  73.         }
  74.         next->next = node;
  75.     }
  76.  
  77. }
  78.  
  79. /* Deqeueu a node from linked list and return the vertex id of the
  80.    removed node.
  81.  
  82.    Note that the input parameters is of type adj_node_t**, but in the
  83.    beginning, it dereferences it to adj_node_t* head. So you are
  84.    essentially passing in a pointer to adj_node_t*.
  85.  
  86.    input parameters:
  87.        adj_node_t**     pointer to an adj_node_t* , whic is essentially
  88.                         the adjacency list of a PARTICULAR vertex, but
  89.                         passed in by refrence.
  90.    return parameters:
  91.        int vid      the vertex ID (vid) of the removed node
  92.  */
  93. int remove_node(adj_node_t** list)
  94. {
  95.     int vid = -1;
  96.  
  97.     // if list valid - this should really never happen
  98.     if(list != NULL) {
  99.         adj_node_t* head = *list;
  100.         // if list is not empty - this can happen if this
  101.         // vertex has no neighbors left
  102.         if(head != NULL) {
  103.             adj_node_t* tmp = head;
  104.             vid = head->vid;
  105.             head = head->next;
  106.             // don't foget to free the removed node
  107.             free(tmp);
  108.         }
  109.         *list = head;
  110.     } else {
  111.         fprintf(stderr, "Adjacency list is NULL\n");
  112.         exit(EXIT_FAILURE);
  113.     }
  114.  
  115.     return vid;
  116.  
  117. }
  118.  
  119.  
  120. /* This function constructs an adjacency list for a graph from an adjacency
  121.    matrix
  122.    input parameters:
  123.        The following are 'consumed' by this function
  124.        int**         adj_mat    2D array that stores the adjacency matrix
  125.        int           rows   # of rows in the matrix
  126.        int           cols   # of columns in the matrix
  127.  
  128.        The following are 'produced' by this function
  129.        adj_node_t*** list   a linked list of adjacencies
  130.  
  131.    return parameters:
  132.        none  
  133.  
  134.    adj_node_t*** list is passed in by reference from the main function so that
  135.    it can be malloc'd via the init_adj_list function.
  136.    After initializing it go through each row and add its adjacent nodes
  137.  */
  138. void construct_adj_list(int** adj_mat, int rows, int cols, adj_node_t*** list)
  139. {
  140.     // verify that the adj matrix is correct
  141.     if(rows != cols) {
  142.         fprintf(stderr, "Adjacency matrix is not square\n");
  143.         exit(EXIT_FAILURE);
  144.     }
  145.     fprintf(stdout, "Constructing the adjacency list for this graph ... ");
  146.  
  147.     // Initialize the linked list
  148.     init_adj_list(list, rows);
  149.  
  150.     // Since list was passed in by reference, accessing its
  151.     // elements would require dereferencing it every time.
  152.     // To make it easier, create a copy of the dereferenced
  153.     // list and store it in myList for use in this function
  154.     adj_node_t** myList = *list;
  155.  
  156.  
  157.     // INSERT YOUR CODE HERE
  158.     // HINT: You will need to use create_node() and add_node() here
  159.     // Go through each vertex and construct its adjacency list
  160.     for(int i = 0; i < rows; i++) {
  161.         for(int j = 0; j < cols; j++) {
  162.             if(adj_mat[i][j] == 1) {
  163.                 adj_node_t* node = create_node(j);
  164.                 add_node(myList, i, node);
  165.             }
  166.         }
  167.     }
  168.  
  169.     fprintf(stdout, "done\n");
  170. }
  171.  
  172. /* This function takes in an adjacency ilst and prints out the list,
  173.    one row/vertext at a time
  174.    input parameters:
  175.        adj_node_t** list    adjacency list for the graph
  176.        int          rows    # of rows/vertices in the graph
  177.    return parameters:
  178.        none
  179.  */
  180. void print_adj_list(adj_node_t** list, int rows)
  181. {
  182.     assert(list);
  183.  
  184.     fprintf(stdout, "---- Print Adj. List ----\n");
  185.     for(int i = 0; i < rows; i++) {
  186.         fprintf(stdout, "|%d| -> ", i);
  187.         adj_node_t* next = list[i];
  188.         while(next != NULL) {
  189.             fprintf(stdout, "%d -> ", next->vid);
  190.             next = next->next;
  191.         }
  192.         fprintf(stdout, "END\n");
  193.     }
  194.     fprintf(stdout, "--------\n\n");
  195. }
  196.  
  197. void free_adj_list(adj_node_t** list, int rows)
  198. {
  199.     if(list != NULL) {
  200.         for(int i = 0; i < rows; i++) {
  201.             if(list[i] != NULL) {
  202.                 adj_node_t* head = list[i];
  203.                 do {
  204.                     adj_node_t* tmp = head;
  205.                     head = head->next;
  206.                     free(tmp);
  207.                 } while(head != NULL);
  208.             }
  209.         }
  210.         free(list);
  211.     }
  212.  
  213.    
  214. }
  215.  
  216. void print_bfs_result(int rows, int* color, int* distance, int* parent)
  217. {
  218.     assert(color);
  219.     assert(distance);
  220.     assert(parent);
  221.  
  222.     printf("---- Print BFS Result ----\n");
  223.     printf("Vert\tCol\tDis\tParent\n");
  224.     for(int i = 0; i < rows; i++) {
  225.         printf("%d\t%d\t%d\t%d\n", i, color[i], distance[i], parent[i]);
  226.     }
  227.     printf("--------\n\n");
  228. }
  229.  
  230.  
  231. /* Do the list-based BFS, given the source node and the graph's adjacency
  232.    list.
  233.    Go through each vertices in a BFS manner, and then calculate the dsitance
  234.    from the source vertex.
  235.        input parameters:
  236.        The following are 'consumed' by this function
  237.        adj_node_t** list        adjacency list for the graph
  238.        int          rows        number of rows/vertices in the graph
  239.        int          source      BFS source
  240.  
  241.        The following are 'produced' by this function
  242.        int*         color       keeps track of color during BFS
  243.        int*         distance        distance from the source
  244.        int*         parent      parent of each vertex
  245.    return parameters:
  246.        none
  247.  */
  248. void bfs(adj_node_t** list, int rows, int source,
  249.          int* color, int* distance, int* parent)
  250. {
  251.     // Make sure the source is a valid vertex
  252.     if(source >= rows) {
  253.         fprintf(stderr, "Invalid source vertex\n");
  254.         exit(EXIT_FAILURE);
  255.     }
  256.     // Make sure the adjacency list is not NULL
  257.     // Even if this is a completely unconnected graph,
  258.     // it should still NOT be NULL (see init_adj_list)
  259.     if(list == NULL) {
  260.         fprintf(stderr, "There is nothing in the adjacency list\n");
  261.         exit(EXIT_FAILURE);
  262.     }
  263.     // Make sure all these are properly allocated (i.e., not NULL)
  264.     assert(color);
  265.     assert(distance);
  266.     assert(parent);
  267.  
  268.     fprintf(stdout, "Breadth first search on the grahp using linked list ... ");
  269.  
  270.     // INSERT YOUR CODE HERE
  271.  
  272.     // Initialize the vertices
  273.     // color should be initialized to 0
  274.     // distance should be initialized to -1 for infinity
  275.     // parent should be initialized to -1 for NIL
  276.     for(int i = 0; i < rows; i++) {
  277.         color[i] = 0;
  278.         distance[i] = -1;
  279.         parent[i] = -1;
  280.     }
  281.  
  282.     // Initialize the source vertex
  283.     // distance for the source vertex is 0, so it should be initialized as such
  284.     // it has no parent, so initialize it to -1
  285.     // color should be initialized to 1
  286.     distance[source] = 0;
  287.     color[source] = 1;
  288.     parent[source] = -1;
  289.  
  290.     // Initialize the queue with the source vertex
  291.     // HINT: use create_node(source) and add_node
  292.     adj_node_t* node = create_node(source);
  293.     add_node(list, source, node);
  294.  
  295.     // bfs iteration
  296.     // HINT: use remove_node (to fetch & dequeu the vertex)
  297.     // HINT: you will also need create_node an add_node here
  298.     while(list[source] != NULL) {
  299.         int vertex = remove_node(list);
  300.  
  301.         adj_node_t* current = list[vertex];
  302.         while(current != NULL) {
  303.             int neighbor = current->vid;
  304.             if(color[neighbor] == 0) {
  305.                 color[neighbor] = 1;
  306.                 distance[neighbor] = distance[vertex] + 1;
  307.                 parent[neighbor] = vertex;
  308.                 adj_node_t* node = create_node(neighbor);
  309.                 add_node(list, neighbor, node);
  310.             }
  311.             current = current->next;
  312.         }
  313.         color[vertex] = 2;
  314.     }
  315.  
  316.    fprintf(stdout, "done\n");
  317.  
  318.     #if DEBUG
  319.         print_bfs_result(rows, color, distance, parent);
  320.     #endif
  321. }
  322.  
  323.  
Advertisement
Add Comment
Please, Sign In to add comment