---恢复内容开始---
目录:
- Graph 实现
- DFS:深度优先搜索
- stack 实现
- recursion 实现
- BFS:广度优先搜索(queue)
1. Graph 实现
1.1 二维数组实现
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; }
1.2 Linked List 实现
GraphAL.c
// 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, e.w)) { 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,深度优先搜索
2.1 通过 stack 来实现(后进先出)
- 首先 push 进去一个 vertex(任意一个顶点,一般选择 0)
- 以下为 while 循环内容,条件为栈不为空
- 然后 pop 出来,并记录 v 值
- 判断 v 是否访问过
- 从大到小遍历所有与 v 相连的 w
- 并将所有的 w 依次 push 入栈
- 执行完之后,进行下一轮的循环
- 首先 pop 出来的是上一轮最后入栈的 w
- 然后继续遍历次 w 的所有邻接点
- 不停的便利下去,直到遍历到头了
- 然后再不停的 pop,遇到访问的顶点直接就 pass 了
- 遇到没有访问的顶点就继续遍历
- 往复循环
- 直到最后所有的点都 pop 了,stack 为空的时候停止
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[e.w][e.v] = 0; g->nE--; } } } return; }
2.2 通过 recursion 来实现
3. BFS:Breadth First Search,广度优先搜索
通过 queue 来实现(先进先出)
- 算法与 DFS 一致,只是将 stack 换成了 queue
- 将邻接点都 push 进去后,再 pop
- 由于是 queue,因此会依次先将邻接点进行 pop
- 然后再 pop 邻接点的所有邻接点
- 相当于树的分层遍历
// 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
---恢复内容结束---