A graph is a flexible data structure that is used to describe the relationship between objects and the connection model.
Algorithms for graphs: minimum spanning tree, shortest path, travel quotient problem, and many other algorithms will be used to breadth-first search and depth-first search , because they provide a set of methods to systematically access graph data structures.
A weighted graph refers to a value or a right on each edge of the graph, which is marked on the edge with a small number. Many conditional factors can be used as weights, but usually it represents the cost of traversing this edge .
A brief introduction to the minimum spanning tree
We make a simple model, nail some nails on a piece of wood and connect it with some strings, assuming each nail is connected by one or more strings. Now let's take the string one at a time until all the nails are connected with the smallest string. The idea behind this model is the minimal spanning tree.
The formal representation is that given a non-directional weighted graph g= (v,e), the minimum spanning tree is set T,T is the smallest set of edge E used to connect all vertices in V at the lowest cost. The edges in the set T can form a tree, because each vertex can find its parent node (except for root nodes).
Prim algorithm
The prim algorithm is a method of generating a minimum spanning tree .
The prim algorithm starts at any vertex, selects one vertex closest to the current vertex at a time, and joins the edges between the two vertices into the tree .
fundamentally speaking, the prim algorithm is the constant choice of vertices, and calculates the weights of the edges, while judging whether there is a more efficient way to connect . The algorithm is similar to the breadth-first search algorithm, because it first traverses all vertices related to this vertex before exploring the deeper vertices in the diagram. each stage determines which vertex to select, so the color and key values of the vertices need to be maintained .
Start by setting the color value of all vertices to white and the key value to ∞ (it represents a large enough number, which is greater than the weight of all edges in the graph). At the same time, set the starting vertex's key value to 0. As the algorithm evolves, a parent node is assigned to each vertex (except for the starting vertex) in the smallest spanning tree. This vertex is part of the most niche tree only when the color value of the vertex changes to black.
The prim algorithm runs as follows:
First, in all the white vertices in the graph, select the vertex u with the lowest key value. At the beginning, the vertex with the key value set to 0 will be the starting vertex.
When this vertex is selected, it is marked black.
Next, for each vertex that is adjacent to U, set the key value of V as the weight of the Edge (U,V), and set U to the parent node of V.
Repeat the process until all the vertices are marked black.
As the smallest spanning tree grows, the tree contains all the edges in the graph (the minimum number of edges that connect all vertices), and each edge has a black vertex at each end.
Shows the generation process of the minimum spanning tree. In the diagram, the key and parent nodes are displayed next to each vertex, separated by a slash. The key value is displayed on the left side of the slash, and the parent node appears to the right of the slash. The light gray Edge is the edge of the minimum spanning tree growth process. The total weighted value of the minimum spanning tree in the figure is 17.
Interface definition for the minimum spanning tree
Mst
int MST (Graph *graph, const Mstvertex *start, List *span, int (*match) (const void *key1, const void *key2));
return value : returns 0 if the minimum spanning tree is calculated, otherwise returns-1.
Description : Calculates the minimum spanning tree for a weighted graph graph with no direction .
The minimum spanning tree starts with the vertex start.
This changes the graph, so if necessary, make a backup of the diagram before calling this operation.
each vertex in graph must contain data of type Mstvertex . By setting the value of the member weight in the Mstvertex struct to specify the weight of each edge , thevalue of weight is determined by the parameter data2 the incoming Graph_ins_edge . Use the member data of the Mstvertex struct to store vertex-related data.
The match function of graph (called when the function is initialized with Graph_init) is used to compare data members in the Mstvertex struct. This function is the same as the parameter match in the incoming MST.
Once the calculation is complete, the relevant data for the minimum spanning tree will be returned to span. span is a list of MSTVERTEX structures that are stored . In span, the vertex of the parent node being null is the root node of the smallest spanning tree. The parent member of each other vertex points to the vertex that precedes the vertex in the span.
the vertices in span point to the actual vertices in graph, so as long as you can access span, the function caller must ensure that the memory space in graph is valid . Once you no longer use span, call List_destroy to destroy span.
complexity : O (e V2), where V is the number of vertices in the graph, and E is the number of edges.
Implementation and analysis of the minimum spanning tree
In order to calculate a minimum spanning tree with a weighted graph without direction, first, we use the basic abstract data type of the representation graph to represent the weighted graph. At the same time, the prim algorithm needs a method of tracking vertex and edge information. This uses the MSTVERTEX structure: it is used to calculate the minimum spanning tree for the vertices in the graph. This structure consists of 5 members: data is a vertex-dependent, weight is the weight of the edge to which the vertex is reached; color is the colour of the vertex; key is the key value of the vertex; the parent is the node of the vertex in the smallest spanning tree.
The process of building a diagram that contains a MSTVERTEX structure is almost identical to the process of building a diagram containing other types: to insert a vertex into the diagram, call Graph_ins_vertex, and pass the Mstvertex struct to data. Similarly, to insert an edge into the diagram, call the function Graph_ins_edge and pass the Mstvertex struct to data1 and data2. When a vertex is inserted, only the data member of the MSTVERTEX structure is set. When inserting an edge, set the data member of the DATA1, data2 data and weight members. In Data2, weight is the weight of the edge, which is the connector of the vertex in the data1 to the vertex in the data2. In practice, weights are usually stored and calculated with floating-point numbers. Because the key value is calculated from the weight value, the key value is also represented by a floating-point number.
the MST operation first initializes each vertex in the adjacency table structure list. Initializes the key value of each vertex to Dbl_max (except for the hyper-starting vertex, the hyper-starting vertex is the initial value of 0.0). In the abstract data type of the graph, the graph is represented by an adjacency table structure linked list. Each adjacency table contains a collection of vertices and an adjacent vertex. Maintains vertex color values, key values, and parent nodes with vertices stored in the adjacency table structure. The key to maintaining the information in the list of adjacency table structures is that it can be stored instead of just the vertices that are adjacent to them. Since a vertex may appear in numerous adjacency tables, each vertex can only appear once in the list of contiguous table structures.
the core of the prim algorithm is to iterate over each node in the diagram with a single loop . In the course of each iteration:
First, select the vertices with the lowest key values in all the white vertices . At the same time, this vertex is blacked out in the adjacency table structure list.
Next, traverse the vertices adjacent to the selected vertex. When iterating through each vertex, check its color and key values in the list of adjacent table structures. Once this information is obtained, it is compared to the color and key values of the selected vertex. If the adjacent vertex is white and its key value is smaller than the selected vertex, the weight of the edge between the selected vertex and the adjacent vertex is set to the key value of the adjacent vertex, and the parent node of the adjacent vertex is set to the selected vertex .
then, update the information stored in adjacent vertices in the list of adjacency table structures.
Repeat the process until all the vertices are blackened.
Once the main loop in the prim algorithm is finished, the minimum spanning tree is calculated. at this point, each black Mstvertex structure in the list of adjacency table structures is inserted into the linked list span . In span, a vertex with a null parent node is the root node of the smallest spanning tree. The parent member of each other vertex points to the vertex that precedes the vertex in the span. The member weight of each Mstvertex struct is not used frequently because it is only used when stored in the adjacency table.
Shows the MSTVERTEX structure list returned by the calculation of the smallest spanning tree in the example diagram above:
Example: the header file of the graph algorithm (including the minimum spanning tree, shortest path, the travel quotient problem three kinds of header files that implement the required function definition)
/*graphalg.h*/#ifndef Graphalg_h#defineGraphalg_h#include"graph.h"#include"list.h"/*define data structures for nodes in the minimum spanning tree*/typedefstructmstvertex_{void*data; Doubleweight; Vertexcolor color; DoubleKdy; structMstvertex_ *parent;} Mstvertex; /*define data structures for nodes in the shortest path*/typedefstructpathvertex_{void*data; Doubleweight; Vertexcolor color; DoubleD; structPathvertex_ *parent;} Pathvertex;/*define the data structure of the nodes in the traveling quotient problem*/typedefstructtspvertex_{void*data; Doublex, y; Vertexcolor color;} Tspvertex;/*function Interface*/intMST (Graph *graph,ConstMstvertex *start, List *span,int(*match) (Const void*key1,Const void*key2));intShortest (Graph *graph,ConstPathvertex *start, List *paths,int(*match) (Const void*key1,Const void*key2));intTSP (List *vertexs,ConstTspvertex *start, List *tour,int(match*) (Const void*key1,Const void*key2));#endif //Graphalg_h
Example: computing the implementation of the minimum spanning tree
/*mst.c*/#include<float.h>#include<stdlib.h>#include"graph.h"#include"list.h"/*MST calculates the minimum spanning tree function*/intMST (Graph *graph,ConstMstvertex *start, List *Span,int(*match) (Const void*key1,Const void*Key2)) {Adjlist*adjlist; Mstvertex*Mst_vertex,*Adj_vertex; LISTELMT*element,*member; DoubleMinmum; intFound,i; /*all nodes in the initialization diagram*/found=0; for(Element=list_head (&graph_adjlists graph); element!=null; element =List_next (Element)) {Mst_vertex= ((Adjlist *) List_data (Element))Vertex; if(Match (Mst_vertex,start)) {/*match to the starting vertex and initialize it*/Mst_vertex->color =White ; Mst_vertex->key =0; Mst_vertex->parent =NULL; Found=1; } Else { /*initialization of non-starting vertices*/Mst_vertex->color =White ; Mst_vertex->key =Dbl_max; Mst_vertex->parent =NULL; } } /*The starting vertex was not found and the function returned*/ if(!found)return-1; /*using prim algorithm to calculate the minimum spanning tree*/I=0; while(i<Graph_vcount (graph)) { /*Select a white vertex with a minimum key value*/Minimum=Dbl_max; for(element = List_head (&graph_adjlists (graph)); element = NULL; element =List_next (Element)) {Mst_vertex= ((Adjlist *) List_data (Element))Vertex; if(Mst_vertex->color = = White && Mst_vertex->key <minmum) {Minmum= mst_vertex->key; Adjlist=list_data (Element); } } /*Paint the selected vertices black*/((Mstvertex*) Adjlist->vertex)->color =Black; /*traverse all adjacent vertices of the selected vertex*/ for(member = List_head (&adjlist->adjacent); member! = NULL; member =List_next (member)) {Adj_vertex=List_data (member); for(element = List_head (&graph_adjlists (graph)); Element! = NULL; Elemet =List_next (Element)) {Mst_vertex= ((Adjlist *) List_data (Element))Vertex; if(Match (Mst_vertex,adj_vertex)) {/*determines whether to change the key value or parent node of the vertex*/ if(Mst_vertex->color = = White && adj_vertex->weight < mst_vertex->key) {Mst_vertex->key = adj_vertex->weight; Mst_vertex->parent =Adjlist_vertex; } Break; } } } /*prepare to pick the next vertex*/I++; }/*load the smallest spanning tree into the linked list*/List_init (span,null);/*load each black node from the list of contiguous table structures*/ for(element = List_head (&graph_adjlists (graph)); Elemet! = NULL; element =List_next (Element)) { /**/Mst_vertex= ((Adjlist *) List_data (Element))Vertex; if(Mst_vertex->color = =Black) { if(List_ins_next (span, list_tail (span), mst_vertex)! =0) {List_destroy (span); return-1; } }} return 0;}