--- --- restore content begins
table of Contents:
- Graph achieve
- DFS: depth-first search
- stack to achieve
- recursion realization
- BFS: breadth-first search (queue)
1. Graph achieve
1.1 two-dimensional array to achieve
GraphAM.c
// GraphAM.c: an adjacency matrix implementation #include <stdio.h> #include <stdlib.h> #include "Graph.h" struct graphRep { int nV; // #vertices int nE; // #edges int **edges; // matrix of Booleans ... THIS IS THE ADJACENCY MATRIX }; Graph newGraph(int numVertices) { Graph g = NULL; if (numVertices < 0) { fprintf(stderr, "newgraph: invalid number of vertices\n"); } else { g = malloc(sizeof(struct graphRep)); if (g == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } g->edges = malloc(numVertices * sizeof(int *)); if (g->edges == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } int v; for (v = 0; v < numVertices; v++) { g->edges[v] = malloc(numVertices * sizeof(int)); if (g->edges[v] == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } for (int j = 0; j < numVertices; j++) { g->edges[v][j] = 0; } } g->nV = numVertices; g->nE = 0; } return g; } Graph freeGraph(Graph g) { if (g != NULL) { int i; for (i = 0; i < g->nV; i++) { free(g->edges[i]); // free the mallocs for each row ... } free(g->edges); // now the malloc for the edges array ... free(g); // now the malloc for the graph rep } return g; } void showGraph(Graph g) { // print a graph if (g == NULL) { printf("NULL graph\n"); } else { printf("V=%d, E=%d\n", g->nV, g->nE); int i; for (i = 0; i < g->nV; i++) { int nshown = 0; int j; for (j = 0; j < g->nV; j++) { if (g->edges[i][j] != 0) { printf("%d-%d ", i, j); nshown++; } } if (nshown > 0) { printf("\n"); } } } return; } static int validV(Graph g, Vertex v) { // checks if v is in graph return (v >= 0 && v < g->nV); } Edge newE(Vertex v, Vertex w) { // create an edge from v to w Edge e = {v, w}; return e; } void showE(Edge e) { // print an edge printf("%d-%d", e.v, e.w); return; } int isEdge(Graph g, Edge e) { // return 1 if edge found, otherwise 0 int found = 0; if (g != NULL && validV(g, e.v) && validV(g, e.w)) { found = (g->edges[e.v][e.w] == 1); } return found; } void insertE(Graph g, Edge e) { // insert an edge into a graph if (g == NULL) { fprintf(stderr, "insertE: graph not initialised\n"); } else { if (!validV(g, e.v) || !validV(g, e.w)) { fprintf(stderr, "insertE: invalid vertices %d-%d\n", e.v, e.w); } else { if (isEdge(g, e) == 0) { // increment nE only if it is new g->nE++; } g->edges[e.v][e.w] = 1; g->edges[e.w][e.v] = 1; } } return; } void removeE(Graph g, Edge e) { // remove an edge from a graph if (g == NULL) { fprintf(stderr, "removeE: graph not initialised\n"); } else { if (!validV(g, e.v) || !validV(g, e.w)) { fprintf(stderr, "removeE: invalid vertices\n"); } else { if (isEdge(g, e) == 1) { // is edge there? g->edges[e.v][e.w] = 0; g->edges[e.w][e.v] = 0; g->nE--; } } } return; }
Achieved 1.2 Linked List
Grfalakc
// GraphAL.c: an adjacency list implementation #include <stdio.h> #include <stdlib.h> #include "Graph.h" typedef struct node *list; struct node { Vertex name; list next; }; struct graphRep { int nV; // #vertices int nE; // #edges list *edges; // array of linked lists ... THIS IS THE ADJACENCY LIST }; Graph newGraph(int numVertices) { Graph g = NULL; if (numVertices < 0) { fprintf(stderr, "newgraph: invalid number of vertices\n"); } else { g = malloc(sizeof(struct graphRep)); if (g == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } g->edges = malloc(numVertices * sizeof(int *)); if (g->edges == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } int v; for (v = 0; v < numVertices; v++) { g->edges[v] = NULL; } g->nV = numVertices; g->nE = 0; } return g; } Graph freeGraph(Graph g) { if (g != NULL) { int i; for (i = 0; i < g->nV; i++) { List node = g->edges[i]; // maybe NULL, maybe points to first node while (node != NULL) { List tmp = node; // save the node node = node->next; // move onto the next node free(tmp); // free the saved node } } free(g->edges); // now the malloc for the edges array ... free(g); // now the malloc for the graph rep } return g; } void showGraph(Graph g) { // print a graph if (g == NULL) { printf("NULL graph\n"); } else { printf("V=%d, E=%d\n", g->nV, g->nE); int i; for (i = 0; i < g->nV; i++) { int nshown = 0; list listV = g->edges[i]; while (listV != NULL) { //printf("g->edges[%d]=%p\n",i ,listV); printf("%d-%d ", i, listV->name); nshown++; listV = listV->next; } if (nshown > 0) { printf("\n"); } } } return; } static int validV(Graph g, Vertex v) { // checks if v is in graph return (v >= 0 && v < g->nV); } Edge newE(Vertex v, Vertex w) { Edge e = {v, w}; return e; } void showE(Edge e) { // print an edge printf("%d-%d", e.v, e.w); return; } int isEdge(Graph g, Edge e) { // return 1 if edge found, otherwise 0 // a linear search for edge 'e': return 1 if edge found, 0 otherwise int found = 0; if (g != NULL && validV(g, e.v) &&validV (g, ew)) { list curr; for (curr = g->edges[e.v]; curr != NULL && !found; curr = curr->next) { if (curr->name == e.w) { found = 1; } } } return found; } void insertE(Graph g, Edge e){ if (g == NULL) { fprintf(stderr, "insertE: graph not initialised\n"); } else { if (!validV(g, e.v) || !validV(g, e.w)) { fprintf(stderr, "insertE: invalid vertices %d-%d\n", e.v, e.w); } else { if (isEdge(g, e) == 0) { list newnodev = malloc(sizeof(struct node)); list newnodew = malloc(sizeof(struct node)); if (newnodev == NULL || newnodew == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } newnodev->name = e.w; // put in the data newnodev->next = g->edges[e.v]; // link to the existing list attached to e.v g->edges[e.v] = newnodev; // link e.v to new node newnodew->name = e.v; newnodew->next = g->edges[e.w]; g->edges[e.w] = newnodew; g->nE++; } } } return; } void removeE(Graph g,Edge e) { int success = 0; List n = g->edges[v]; // n is the start node List p = NULL; // p is previous node to n while (n != NULL && !success){ // linear search for w if (n->name == w) { List nn = n->next; // we've found w, we want to skip over it if (p == NULL) { // if w is first node, p will be NULL g->edges[v] = nn; } else { p->next = nn; } free(n); success = 1; } p = n; n = n->next; } return success; }
2. DFS: Deep First Search, depth-first search
2.1 is achieved (LIFO) stack by
- A first push into Vertex (arbitrary vertex, usually selected 0)
- The following is the contents of the while loop, the condition for the stack is not empty
- Then pop it out and record the value of v
- V determine whether visited
- V and w descending through all connected
- And all of w in turn push the stack
- After execution, the next round of the cycle
- First pop out of the last round of the last stack of w
- Then continue through all the neighbors of w times
- Stop convenience to go down through the coming to an end
- Then stop pop, met accessed directly pass the vertex
- Vertex encountered no access would continue to traverse
- Cyclical
- Until finally all points pop up, stack is empty when to stop
dfsquack.c
// graphAM.c: an adjacency matrix implementation #include <stdio.h> #include <stdlib.h> #include "Graph.h" struct graphRep { int nV; // #vertices int nE; // #edges int **edges; // matrix of Booleans ... THIS IS THE ADJACENCY MATRIX }; Graph newGraph(int numVertices) { Graph g = NULL; if (numVertices < 0) { fprintf(stderr, "newgraph: invalid number of vertices\n"); } else { g = malloc(sizeof(struct graphRep)); if (g == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } g->edges = malloc(numVertices * sizeof(int *)); if (g->edges == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } int v; for (v = 0; v < numVertices; v++) { g->edges[v] = malloc(numVertices * sizeof(int)); if (g->edges[v] == NULL) { fprintf(stderr, "newGraph: out of memory\n"); exit(1); } for (int j = 0; j < numVertices; j++) { g->edges[v][j] = 0; } } g->nV = numVertices; g->nE = 0; } return g; } Graph freeGraph(Graph g) { if (g != NULL) { int i; for (i = 0; i < g->nV; i++) { free(g->edges[i]); // free the mallocs for each row ... } free(g->edges); // now the malloc for the edges array ... free(g); // now the malloc for the graph rep } return g; } void showGraph(Graph g) { // print a graph if (g == NULL) { printf("NULL graph\n"); } else { printf("V=%d, E=%d\n", g->nV, g->nE); int i; for (i = 0; i < g->nV; i++) { int nshown = 0; int j; for (j = 0; j < g->nV; j++) { if (g->edges[i][j] != 0) { printf("<%d %d> ", i, j); nshown++; } } if (nshown > 0) { printf("\n"); } } } return; } static int validV(Graph g, Vertex v) { // checks if v is in graph return (v >= 0 && v < g->nV); } Edge newE(Vertex v, Vertex w) { // create an edge from v to w Edge e = {v, w}; return e; } void showE(Edge e) { // print an edge printf("%d-%d", e.v, e.w); return; } int isEdge(Graph g, Edge e) { // return 1 if edge found, otherwise 0 int found = 0; if (g != NULL && validV(g, e.v) && validV(g, e.w)) { found = (g->edges[e.v][e.w] == 1); } return found; } void insertE(Graph g, Edge e) { // insert an edge into a graph if (g == NULL) { fprintf(stderr, "insertE: graph not initialised\n"); } else { if (!validV(g, e.v) || !validV(g, e.w)) { fprintf(stderr, "insertE: invalid vertices %d-%d\n", e.v, e.w); } else { if (isEdge(g, e) == 0) { // increment nE only if it is new g->nE++; } g->edges[e.v][e.w] = 1; g->edges[e.w][e.v] = 1; } } return; } void removeE(Graph g, Edge e) { // remove an edge from a graph if (g == NULL) { fprintf(stderr, "removeE: graph not initialised\n"); } else { if (!validV(g, e.v) || !validV(g, e.w)) { fprintf(stderr, "removeE: invalid vertices\n"); } else { if (isEdge(g, e) == 1) { // is edge there? g->edges[e.v][e.w] = 0; g-> edges [ew] [ev ] = 0; g-> nE--; } } } Return; }
2.2 is achieved by recursion
3. BFS: Breadth First Search, BFS
To achieve (FIFO) queue by
- DFS algorithm is consistent with, but the stack into the queue
- After neighbors are push in, then pop
- Because it is queue, thus in turn adjacent first point pop
- Then pop all the neighbors of neighbors
- The equivalent of a hierarchical tree traversal
// bfsquack.c: traverse a graph using bfs and a stack implementation #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include "Graph.h" #include "Quack.h" void bfs(Graph, Vertex, int); #define WHITESPACE 100 int readNumV(void) { // returns the number of vertices numV or -1 int numV; char w[WHITESPACE]; scanf("%[ \t\n]s", w); // skip leading whitespace if ((getchar() != '#') || (scanf("%d", &numV) != 1)) { fprintf(stderr, "missing number (of vertices)\n"); return -1; } return numV; } int readGraph(int numV, Graph g) { // reads number-number pairs until EOF int success = true; // returns true if no error int v1, v2; while (scanf("%d %d", &v1, &v2) != EOF && success) { if (v1 < 0 || v1 >= numV || v2 < 0 || v2 >= numV) { fprintf(stderr, "unable to read edge\n"); success = false; } else { insertE(g, newE(v1, v2)); } } return success; } void bfs(Graph g, Vertex v, int numV) { int *mallocArray(int numV) { int *v = malloc(numV * sizeof(int)); if (v == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } int i; for (i=0; i<numV; i++) { v[i] = UNVISITED; } return v; } void showArray(int *v, int numV) { int i; printf("Visited: {"); for (i=0; i<numV; i++) { printf("%d", v[i]); if (i <= numV-2) { printf(", "); } } printf("}\n"); return; } int *visited = mallocArray(numV); Quack s = createQuack(); qush(v, s); showQuack(s); int order = 0; while (!isEmptyQuack(s)) { v = pop(s); if (visited[v] == UNVISITED) { showArray(visited, numV); //printf("visited[%d]=%d\n", v, order); visited[v] = order++; Vertex w; for (w=0; w<=numV-1; w++) { if (isEdge(g, newE(v,w))) { qush (w, s); } } } showQuack(s); } showArray(visited, numV); free(visited); return; } int main (void) { int numV; if ((numV = readNumV()) >= 0) { Graph g = newGraph(numV); if (readGraph(numV, g)) { showGraph(g); bfs(g, 0, numV); } g = freeGraph(g); g = NULL; } else { return EXIT_FAILURE; } return EXIT_SUCCESS; } // clear && gcc bfsquack.c GraphAM.c Quack.c && ./a.out < input_path.txt // clear && gcc dfs_path_searching.c GraphAM.c Quack.c && ./a.out < input_path.txt
--- end --- restore content