Data Structure-using the C language to store and represent graph adjacent tables
// Storage representation of the graph array (Adjacent matrix) # include
# Include
# Include
# 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; // struct ArcNode * nextarc of the vertex to which the arc points; // InfoType * info of the pointer to the next arc; // weight pointer of the network} ArcNode; // table node typedef stru Ct 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; // team head pointer, pointer field pointing to team head element team end finger Needle, pointing to the end element} LinkQueue; // positioning function // If vertex u exists in G, the position of the vertex is returned in the graph; otherwise,-1 is returned. Int LocateVex (ALGraph G, VertexType u) {int I; for (I = 0; I
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; // Insert 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 (serial number) q = p; p = p-> nextarc ;}} return 1 ;}// add an arc to G
If G is undirected, a symmetric arc is added.
. 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
If G is undirected, the symmetric arc is also deleted.
. 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
{// P points to the next arc q = p; p = p-> nextarc;} if (p & p-> adjvex = j) // locate the Arc
{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
{P = (* G). vertices [j]. firstarc; // p indicates the first arc of the margin while (p & p-> adjvex! = I) // p is not empty and the arc referred to is not the arc to be deleted
{// P points to the next arc q = p; p = p-> nextarc;} if (p & p-> adjvex = I) // locate the Arc
{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 () 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 queues }}} printf () ;}// output graph's adjacent Table G. Void Display (ALGraph G) {int I; ArcNode * p; switch (G. kind) {case DG: printf (Directed Graph); break; case DN: printf (Directed Graph); break; case AG: printf (undirected graph); break; case: printf (undirected network);} printf (% d vertex:, G. vexnum); for (I = 0; I <G. vexnum; ++ I) printf (% s, G. vertices [I]. data); printf (% d arc (edge):, 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 ();}} void print (char * I) {printf (% s, I);} int main () {int I, j, k, n; ALGraph g; VertexType v1, v2; printf (select directed graph); CreateGraph (& g); Display (g); printf (delete an edge or arc. Enter the arc tail arc header of the edge or arc to be deleted :); scanf (% s, v1, v2); DeleteArc (& g, v1, v2); Display (g); printf (modify vertex value, enter the new 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 arc or edge number:); scanf (% d, & n); for (k = 0; k
Effect: