In a directed graph that represents a project, vertices are used to represent activity, and arcs are used to represent priority relationships between activities. Such Directed Graphs represent active networks for vertices, we call it activity on vextex network ). The arc in the AOV network indicates a certain constraint between activities. There cannot be a loop in the AOV network, so that the start of an activity must be completed by itself as a prerequisite. Obviously, this is not acceptable.
Set G = {v, e} To a directed graph with n vertices. vertices in V are V1, V2 ,..., if there is a path from vertex VI to vj, then in the vertex sequence, vertex VI must be before VJ. Then we call this vertex sequence a topological order.
The so-called topological sorting is actually the process of constructing a topological sequence for a directed graph. There will be two results during construction. If all vertices of this network are output, it indicates that it does not have an AOV Network (loop). If the number of output vertices is less, even if one is missing, it also indicates that the network has a loop, not the AOV network.
The basic idea of topological sorting for the AOV network is: select a vertex output with an inbound degree of 0 from the AOV network, delete the vertex, and delete the arc with this vertex as the end, repeat this step until all vertices are output or the vertex with an inbound degree of 0 does not exist in the AOV network.
Because the vertex needs to be deleted during the topological sorting process, it is more convenient to use the structure of the adjacent table. Considering that the algorithm always needs to find the vertex whose input degree is 0, in the original vertex table node structure, we can add an inbound field in, that is, the number of inbound degrees, the preceding operation to delete the arc ending with a vertex also deletes the intermediate connected arc by subtracting 1 from the in of the adjacent vertex of a vertex.
For the first image AOV network in Figure 7-8-2, we can obtain the data structure of the adjacent table in the second figure.
In addition, an auxiliary data structure, stack, is also needed in the algorithm to store points with an inbound value of 0 during processing, the purpose is to avoid traversing the vertex table every time you search for any vertex with an input degree of 0.
Next let's take a look at the overall code (adapted from the big talk data structure).
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
|
# Include <iostream> Using namespace STD;# Define maxedge 20 # Define maxvex 14 # Define infinity 65535 /* Adjacent matrix structure */ Typedef struct { Int vexs [maxvex]; Int arc [maxvex] [maxvex]; Int numvertexes, numedges; } Mgraph; /* The structure of the adjacent table *******************/ Typedef struct edgenode/* edge table node */ { Int adjvex;/* indicates the adjacent vertex field, storing the subscript corresponding to the vertex */ Int weight;/* used to store the weight value, which is not required for non-network graphs */ Struct edgenode * Next;/* link field, pointing to the next adjacent contact */ } Edgenode; Typedef struct vertexnode/* vertex table node */ { Int in;/* vertex inbound */ Int data;/* vertex field, storing vertex information */ Edgenode * firstedge;/* edge header pointer */ } Vertexnode, adjlist [maxvex]; Typedef struct { Adjlist; Int numvertexes, numedges;/* Number of vertices and edges in the graph */ } Graphadjlist, * graphadjlist; /******************************/ Void createmgraph (mgraph * G)/* build graph */ { Int I, J; /* Printf ("Enter the number of edges and the number of vertices :");*/ G-> numedges = maxedge; G-> numvertexes = maxvex; For (I = 0; I <G-> numvertexes; I ++)/* initialization diagram */ { G-> vexs [I] = I; } For (I = 0; I <G-> numvertexes; I ++)/* initialization diagram */ { For (j = 0; j <G-> numvertexes; j ++) { G-> arc [I] [J] = 0; } } G-> arc [0] [4] = 1; G-> arc [0] [5] = 1; G-> arc [0] [11] = 1; G-> arc [1] [2] = 1; G-> arc [1] [4] = 1; G-> arc [1] [8] = 1; G-> arc [2] [5] = 1; G-> arc [2] [6] = 1; G-> arc [2] [9] = 1; G-> arc [3] [2] = 1; G-> arc [3] [13] = 1; G-> arc [4] [7] = 1; G-> arc [5] [8] = 1; G-> arc [5] [12] = 1; G-> arc [6] [5] = 1; G-> arc [8] [7] = 1; G-> arc [9] [10] = 1; G-> arc [9] [11] = 1; G-> arc [10] [13] = 1; G-> arc [12] [9] = 1; } /* Construct an adjacent table using the adjacent matrix */ Void createalgraph (mgraph g, graphadjlist * GL) { Int I, J; Edgenode * E; * GL = (graphadjlist) malloc (sizeof (graphadjlist )); (* GL)-> numvertexes = G. numvertexes; (* GL)-> numedges = G. numedges; For (I = 0; I <G. numvertexes; I ++)/* read vertex information and create a vertex table */ { (* GL)-> adjlist [I]. In = 0; (* GL)-> adjlist [I]. Data = G. vexs [I]; (* GL)-> adjlist [I]. firstedge = NULL;/* set the edge table to an empty table */ } For (I = 0; I <G. numvertexes; I ++)/* Create an edge table */ { For (j = 0; j <G. numvertexes; j ++) { If (G. Arc [I] [J] = 1) { E = (edgenode *) malloc (sizeof (edgenode )); E-> adjvex = J;/* the adjacent number is J */ E-> next = (* GL)-> adjlist [I]. firstedge;/* assign the node pointer pointing to the current vertex to E */ (* GL)-> adjlist [I]. firstedge = E;/* point the pointer of the current vertex to E */ (* GL)-> adjlist [J]. In ++;/* Note that J */ } } } } /* Topological sorting. If GL does not have a loop, the output Topology Sorting sequence is returned and 1 is returned. If there is a loop, 0 is returned. */ Bool topologicalsort (graphadjlist GL) { Edgenode * PE; Int I, K, gettop; Int Top = 0;/* used for the stack pointer subscript */ Int COUNT = 0;/* used to count the number of output vertices */ /* Create a stack and add the vertex with an inbound degree of 0 to the stack */ Int * stack = (int *) malloc (sizeof (GL-> numvertexes * sizeof (INT ))); For (I = 0; I <Gl-> numvertexes; I ++) If (0 = gl-> adjlist [I]. In) Stack [++ top] = I;/* Add a vertex with an inbound degree of 0 to the stack */ While (top! = 0) { Gettop = stack [top --]; Cout <Gl-> adjlist [gettop]. Data <"-> "; Count ++;/* output vertex I and count */ For (PE = gl-> adjlist [gettop]. firstedge; PE; Pe = pe-> next) { K = pe-> adjvex; /* Subtract 1 from the inbound degree of the adjacent contact of vertex I. If the value is 0 after the value is reduced by 1, the inbound operation is performed */ If (! -- Gl-> adjlist [K]. In) Stack [++ top] = K; } } Cout <Endl; If (count <Gl-> numvertexes) Return false; Else Return true; } Int main (void) { Mgraph mg; Graphadjlist GL; Createmgraph (& Mg ); Createalgraph (Mg, & GL ); If (topologicalsort (GL )) Cout <"It's a aov network" <Endl; Else Cout <"it's not a AOV network" <Endl; Return 0; } |
Output:
The algorithm code is easier to understand than the minimum spanning tree and the shortest path, and the comments are also clearer. Here we will not bother to talk about it. For example, 7-8-4 is a simulation map that deletes node V3, other deleted nodes are similar, and so on. It should be noted that there is a createalgraph function that uses the adjacent matrix (pre-determined) to generate the adjacent table. Because it is a directed graph, edgenode is inserted only once for an edge, when initializing in, note the inbound level, that is, (* GL)-> adjlist [J]. in ++;
/* Note: This is J */The createmgraph function that creates the adjacent matrix. Because it is a directed graph, the matrix is not symmetric. In addition, it is not a network chart. Therefore, only 1 indicates that the arc exists, and 0 indicates that the arc does not exist.
Of course, the output result of the program is not the only topological sorting scheme.