Data Structure --- using c language to store and represent the graph's adjacent table --- using c
// Map array (Adjacent matrix) Storage representation # include <stdio. h> # include <stdlib. h> # include <string. h> # define MAX_NAME 3 // the maximum length of the vertex string + 1 # define MAX_VERTEX_NUM 20 typedef int InfoType; // the weight of the stored Network: typedef char VertexType [MAX_NAME]; // string type typedef enum {DG, DN, AG, AN} GraphKind; // {directed graph, directed graph, undirected graph, undirected net} int visited [MAX_VERTEX_NUM]; // access flag array void (* VisitFunc) (char * v); // function variable typedef struct ArcNode {int adjvex; // The Position of the vertex pointed to by the arc struct ArcNode * Nextarc; // The InfoType * info pointer to the next arc; // The weight pointer of the network} ArcNode; // table node typedef struct VNode {VertexType data; // vertex information ArcNode * firstarc; // address of the first table node pointing to the first arc pointer attached to the vertex} VNode, AdjList [MAX_VERTEX_NUM]; // header node typedef struct {AdjList vertices; int vexnum, arcnum; // The number of current vertices and the number of arcs int kind of the graph; // The type mark of the graph} ALGraph; typedef int QElemType; // queue type // Single-Chain queue -- queue chain storage structure typedef struct QNode {QElemType data; // data field struct QNode * next; // pointer Field} QNode, * QueuePtr; typedef struct {QueuePtr front, rear; // The team header pointer. the pointer field points to the team Header element, and the team tail element} LinkQueue; // positioning function // If vertex u exists in G, the vertex is returned in the graph; otherwise,-1 is returned. Int LocateVex (ALGraph G, VertexType u) {int I; for (I = 0; I <G. vexnum; ++ I) if (strcmp (u, G. vertices [I]. data) = 0) return I; return-1;} // create a graph // use the storage structure of the adjacent table, construct graph G without relevant information (use a function to construct four types of graphs ). Int CreateGraph (ALGraph * G) {int I, j, k; int w; // weight VertexType va, vb; ArcNode * p; printf ("Enter the graph type (directed graph: 0, directed graph: 1, directed graph: 2, directed graph: 3): \ n"); scanf ("% d ", & (* G ). kind); printf ("Enter the number of vertices and edges of the graph: (Space) \ n"); scanf ("% d", & (* G ). vexnum, & (* G ). arcnum); printf ("Enter % d vertex values (<% d characters): \ n", (* G ). vexnum, MAX_NAME); for (I = 0; I <(* G ). vexnum; ++ I) // construct the vertex vector {scanf ("% s", (* G ). vertices [I]. data); (* G ). vertices [I]. firstarc = NULL;} if (* G ). kind = 1 | (* G ). kind = 3) // net printf ("Please input the weights, backend and arc headers of each arc (edge) in sequence (separated by spaces ): \ n "); else // figure printf (" Please input the arc tail and arc header of each arc (edge) in sequence (separated by spaces): \ n "); for (k = 0; k <(* G ). arcnum; ++ k) // construct the table node linked list {if (* G ). kind = 1 | (* G ). kind = 3) // scanf ("% d % s", & w, va, vb); else // figure scanf ("% s ", va, vb); I = LocateVex (* G, va); // arc tail j = LocateVex (* G, vb); // arc header p = (ArcNode *) malloc (sizeof (ArcNode); p-> adjvex = j; if (* G ). kind = 1 | (* G ). kind = 3) // Net {p-> info = (int *) malloc (sizeof (int); * (p-> info) = w;} elsep-> info = NULL; // Figure p-> nextarc = (* G ). vertices [I]. firstarc; // Insert the header (* G ). vertices [I]. firstarc = p; if (* G ). kind> = 2) // returns the second table node {p = (ArcNode *) malloc (sizeof (ArcNode); p-> adjvex = I; if (* G ). kind = 3) // undirected network {p-> info = (int *) malloc (sizeof (int); * (p-> info) = w ;} elsep-> info = NULL; // undirected graph p-> nextarc = (* G ). vertices [j]. firstarc ;// Inserted in the header (* G ). vertices [j]. firstarc = p ;}} return 1 ;}// destroy the Gvoid DestroyGraph (ALGraph * G) {int I; ArcNode * p, * q; for (I = 0; I <(* G ). vexnum; ++ I) {p = (* G ). vertices [I]. firstarc; while (p) {q = p-> nextarc; if (* G ). kind % 2) // net free (p-> info); free (p); p = q ;}} (* G ). vexnum = 0; (* G ). arcnum = 0;} // returns the value of v. VertexType * GetVex (ALGraph G, int v) {if (v> = G. vexnum | v <0) exit (0); return & G. vertices [v]. data;} // new value for v. Int PutVex (ALGraph * G, VertexType v, VertexType value) {int I; I = LocateVex (* G, v); if (I>-1) // v is the vertex of G {strcpy (* G ). vertices [I]. data, value); return 1;} return 0;} // returns the sequence number of the first adjacent vertex of v. If the vertex is not adjacent to the vertex in G,-1 is returned. Int FirstAdjVex (ALGraph G, VertexType v) {ArcNode * p; int v1; v1 = LocateVex (G, v ); // v1 is the sequence number of vertex v in graph G, p = G. vertices [v1]. firstarc; if (p) return p-> adjvex; elsereturn-1;} // returns the sequence number of the next adjacent vertex of v (relative to w. If w is the last // adjacent contact of v,-1 is returned. Int NextAdjVex (ALGraph G, VertexType v, VertexType w) {ArcNode * p; int v1, w1; v1 = LocateVex (G, v ); // v1 is the sequence number of vertex v in graph G w1 = LocateVex (G, w); // w1 is the sequence number of vertex w in graph G p = G. vertices [v1]. firstarc; while (p & p-> adjvex! = W1) // the pointer p is not null and the table node is not w p = p-> nextarc; if (! P |! P-> nextarc) // w is not found or w is the last adjacent point return-1; else // p-> adjvex = w // return the serial number of the next adjacent vertex of v (relative to w), return p-> nextarc-> adjvex ;} // Add a new vertex v in graph G (do not add the arc related to the vertex, and leave it for InsertArc ). Void InsertVex (ALGraph * G, VertexType v) {strcpy (* G ). vertices [(* G ). vexnum]. data, v); // construct a new vertex vector (* G ). vertices [(* G ). vexnum]. firstarc = NULL; (* G ). vexnum ++; // Number of vertices in graph G plus 1} // Delete vertex v and Its Related arc in G. Int DeleteVex (ALGraph * G, VertexType v) {int I, j; ArcNode * p, * q; j = LocateVex (* G, v ); // j is the sequence number of vertex v. if (j <0) // v is not the vertex of graph G. return 0; p = (* G ). vertices [j]. firstarc; // Delete the arc or edge while (p) {q = p; p = p-> nextarc; if (* G ). kind % 2) // network free (q-> info); free (q); (* G ). arcnum --; // The number of arcs or edges minus 1} (* G ). vexnum --; // The number of vertices minus 1 for (I = j; I <(* G ). vexnum; I ++) // forward the vertex after vertex v (* G ). vertices [I] = (* G ). vertices [I + 1]; // deletes the v-based Arc or edge and modifies the vertex of the table node if necessary. Position value for (I = 0; I <(* G ). vexnum; I ++) {p = (* G ). vertices [I]. firstarc; // points to 1st arcs or edges while (p) // An edges with an arc {if (p-> adjvex = j) // An edges with v as the inbound degree. {If (p = (* G ). vertices [I]. firstarc) // The number of nodes to be deleted is 1st {(* G ). vertices [I]. firstarc = p-> nextarc; if (* G ). kind % 2) // net free (p-> info); free (p); p = (* G ). vertices [I]. firstarc; if (* G ). kind <2) // directed (* G ). arcnum --; // arc or edge number minus 1} else {q-> nextarc = p-> nextarc; if (* G ). kind % 2) // net free (p-> info); free (p); p = q-> nextarc; if (* G ). kind <2) // directed (* G ). arcnum --; // arc or edge number minus 1} else {if (p-> adjvex> j) p-> adjvex --; // modify the vertex position value (sequence number) of the table Node) Q = p; p = p-> nextarc ;}} return 1 ;}// add an arc to G <v, w>. If G is undirected, the symmetric arc is also added <w, v>. Int InsertArc (ALGraph * G, VertexType v, VertexType w) {ArcNode * p; int w1, I, j; I = LocateVex (* G, v ); // arc tail or edge number j = LocateVex (* G, w); // if (I <0 | j <0) return 0; (* G ). arcnum ++; // The number of arcs or edges of graph G plus 1 if (* G ). kind % 2) // network {printf ("Enter the arc (edge) % s → % s weight:", v, w); scanf ("% d ", & w1);} p = (ArcNode *) malloc (sizeof (ArcNode); p-> adjvex = j; if (* G ). kind % 2) // net {p-> info = (int *) malloc (sizeof (int); * (p-> info) = w1 ;} elsep-> info = NULL; p -> Nextarc = (* G ). vertices [I]. firstarc; // Insert the header (* G ). vertices [I]. firstarc = p; if (* G ). kind> = 2) // undirected, generate another table node {p = (ArcNode *) malloc (sizeof (ArcNode); p-> adjvex = I; if (* G ). kind = 3) // undirected network {p-> info = (int *) malloc (sizeof (int); * (p-> info) = w1 ;} elsep-> info = NULL; p-> nextarc = (* G ). vertices [j]. firstarc; // Insert the header (* G ). vertices [j]. firstarc = p;} return 1 ;}// Delete the arc in G <v, w>. If G is undirected, delete the symmetric arc <w, v>. Int DeleteArc (ALGraph * G, VertexType v, VertexType w) {ArcNode * p, * q; int I, j; I = LocateVex (* G, v ); // I is the serial number of vertex v (arc tail) j = LocateVex (* G, w); // j is the vertex w (ARC header) if (I <0 | j <0 | I = j) return 0; p = (* G ). vertices [I]. firstarc; // p points to the first arc of vertex v while (p & p-> adjvex! = J) // p is not empty and the arc referred to is not the arc to be deleted <v, w >{// p points to the next arc q = p; p = p-> nextarc ;} if (p & p-> adjvex = j) // locate the arc <v, w> {if (p = (* G ). vertices [I]. firstarc) // p refers to 1st arcs (* G ). vertices [I]. firstarc = p-> nextarc; // point to the next arc elseq-> nextarc = p-> nextarc; // point to the next arc if (* G ). kind % 2) // network free (p-> info); free (p); // release this node (* G ). arcnum --; // arc or edge number minus 1} if (* G ). kind> = 2) // undirected, delete symmetric arc <w, v> {p = (* G ). vertices [j]. firstarc; // p indicates the first arc of a margin while (p & p-> adjvex! = I) // p is not empty and the arc referred to is not the arc to be deleted <w, v >{// p points to the next arc q = p; p = p-> nextarc ;} if (p & p-> adjvex = I) // locate the arc <w, v> {if (p = (* G ). vertices [j]. firstarc) // p refers to 1st arcs (* G ). vertices [j]. firstarc = p-> nextarc; // point to the next arc elseq-> nextarc = p-> nextarc; // point to the next arc if (* G ). kind = 3) // undirected network free (p-> info); free (p); // release this node} return 1 ;} // recursively traverse the graph G Based on the v vertex. Void DFS (ALGraph G, int v) {int w; VertexType v1, w1; strcpy (v1, * GetVex (G, v); visited [v] = 1; // set the access flag to 1 (accessed) VisitFunc (G. vertices [v]. data); // access the v vertex for (w = FirstAdjVex (G, v1); w> = 0; w = NextAdjVex (G, v1, strcpy (w1, * GetVex (G, w) if (! Visited [w]) DFS (G, w); // recursively call DFS for the unaccessed neighbor w of v} // performs depth-first traversal on Graph G. Void DFSTraverse (ALGraph G, void (* Visit) (char *) {int v; // use the global variable VisitFunc so that DFS does not have to set the function pointer parameter VisitFunc = Visit; for (v = 0; v <G. vexnum; v ++) visited [v] = 0; // access flag array initialization for (v = 0; v <G. vexnum; v ++) if (! Visited [v]) DFS (G, v); // call DFS printf ("\ n") for unaccessed vertices;} // construct an empty queue Q. Int InitQueue (LinkQueue * Q) {(* Q ). front = (* Q ). rear = (QueuePtr) malloc (sizeof (QNode); // dynamically allocate a space if (! (* Q ). front) exit (0); (* Q ). front-> next = NULL; // The head pointer of the queue points to NULL and has no data fields. This constitutes an empty queue return 1 ;} // Insert a new team-end element whose Element e is Q. Int EnQueue (LinkQueue * Q, QElemType e) {QueuePtr p = (QueuePtr) malloc (sizeof (QNode); if (! P) // storage allocation failure exit (0); // generate a queue element p-> data = e; p-> next = NULL; // connect the new queue element to the backend (* Q ). rear-> next = p; (* Q ). rear = p; return 1 ;}// if the queue is not empty, delete the queue Header element of Q, use e to return its value, and return 1; otherwise, return 0. Int DeQueue (LinkQueue * Q, QElemType * e) {QueuePtr p; if (* Q ). front = (* Q ). rear) return 0; p = (* Q ). front-> next; // The Header element * e = p-> data; (* Q ). front-> next = p-> next; if (* Q ). rear = p) (* Q ). rear = (* Q ). front; free (p); return 1;} // If Q is an empty queue, 1 is returned; otherwise, 0 is returned. Int QueueEmpty (LinkQueue Q) {if (Q. front = Q. rear) return 1; elsereturn 0;} // traverse graph G by extensiveness first. Use the auxiliary queue Q and access flag array visited. Void BFSTraverse (ALGraph G, void (* Visit) (char *) {int v, u, w; VertexType u1, w1; LinkQueue Q; for (v = 0; v <G. vexnum; ++ v) visited [v] = 0; // sets the initial value of InitQueue (& Q); // sets the null auxiliary queue Q for (v = 0; v <G. vexnum; v ++) // if it is a connected graph, only v = 0 will traverse the entire graph if (! Visited [v]) // v has not been accessed {visited [v] = 1; Visit (G. vertices [v]. data); EnQueue (& Q, v); // v enters the queue while (! QueueEmpty (Q) // The queue is not empty {DeQueue (& Q, & u); // The team Header element is set to u strcpy (u1, * GetVex (G, u); for (w = FirstAdjVex (G, u1); w> = 0; w = NextAdjVex (G, u1, strcpy (w1, * GetVex (G, w) if (! Visited [w]) // w is the unaccessed adjacent vertex of u {visited [w] = 1; Visit (G. vertices [w]. data); EnQueue (& Q, w); // w join }}printf ("\ n") ;}// output graph's adjacent Table G. Void Display (ALGraph G) {int I; ArcNode * p; switch (G. kind) {case DG: printf ("Directed Graph \ n"); break; case DN: printf ("Directed Graph \ n"); break; case AG: printf ("undirected graph \ n"); break; case AN: printf ("undirected network \ n");} printf ("% d vertices: \ n", G. vexnum); for (I = 0; I <G. vexnum; ++ I) printf ("% s", G. vertices [I]. data); printf ("\ n % d arc (edge): \ n", G. arcnum); for (I = 0; I <G. vexnum; I ++) {p = G. vertices [I]. firstarc; while (p) {if (G. kind <= 1) // directed to {printf ("% s → % s", G. vertices [I]. data, G. vertices [p-> adjvex]. data); if (G. kind = DN) // network printf (": % d", * (p-> info);} else // undirected (avoid outputting twice) {if (I <p-> adjvex) {printf ("% s-% s", G. vertices [I]. data, G. vertices [p-> adjvex]. data); if (G. kind = AN) // network printf (": % d", * (p-> info) ;}} p = p-> nextarc ;} printf ("\ n") ;}} void print (char * I) {printf ("% s", I) ;}int main () {int I, j, k, n; ALGraph g; VertexType v1, v2; printf ("select directed graph \ n"); CreateGraph (& g); Display (g ); printf ("delete an edge or arc. Enter the arc tail arc header of the edge or arc to be deleted: \ n"); scanf ("% s", v1, v2); DeleteArc (& g, v1, v2); Display (g); printf ("to modify the vertex value, enter the original value :"); scanf ("% s", v1, v2); PutVex (& g, v1, v2); Display (g); printf ("Insert a new vertex, enter the vertex value: "); scanf (" % s ", v1); InsertVex (& g, v1); Display (g ); printf ("insert an arc or edge related to the new vertex. Enter the number of arcs or edges:"); scanf ("% d", & n); for (k = 0; k <n; k ++) {printf ("enter another vertex value:"); scanf ("% s", v2); printf ("For Directed Graphs, enter the direction of another vertex (0: arc header 1: arc tail): "); scanf (" % d ", & j); if (j) insertArc (& g, v2, v1); elseInsertArc (& g, v1, v2);} Display (g); printf ("delete vertices and related arcs or edges, enter the vertex value: "); scanf (" % s ", v1); DeleteVex (& g, v1); Display (g ); printf ("deep-first search results: \ n"); DFSTraverse (g, print); printf ("Results of breadth-first search: \ n"); BFSTraverse (g, print); DestroyGraph (& g); system ("pause"); return 0 ;}
Effect:
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.