[427] Graph implementation and DFS & BFS

--- --- restore content begins

table of Contents:

  1. Graph achieve
  2. DFS: depth-first search
  3. 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

Guess you like

Origin www.cnblogs.com/alex-bn-lee/p/11242024.html