We introduced the tree data structure, the tree is composed of N (n>0) a finite node by connecting their edges to form a hierarchical relationship of the set, call it "tree" because it looks like an upside down tree, including two fork tree, red black tree, 2-3-4 tree , heap and other different trees, there are some of these trees do not understand can refer to my previous several blog. And this blog we will introduce another kind of data structure--diagram, diagram is the most commonly used in computer programming data structure, in the mathematical sense, the tree is a kind of graph, we can compare learning.
1, the definition of the diagram
We know that the data structure discussed above has a framework, and this framework is implemented by the corresponding algorithm, such as the two-tree search tree, the left subtree of all nodes are less than the value of its root node, the right subtree all nodes are greater than the value of its root nodes, similar to this shape makes it easy to search for data and insert data, The edge of the tree represents a shortcut from one node to another.
The figure usually has a fixed shape, which is determined by a physical or abstract problem. The middle node represents the city, while the edge may represent a flight route between cities. The simplified highway network in California, USA:
①, adjacency:
If two vertices are connected by the same edge, it is said that the two vertices are contiguous, such as I and G are contiguous, and I and F are not. Sometimes a vertex that is adjacent to a specified vertex is called its neighbor, such as the neighbor of Vertex G is I, H, F.
②, Path:
The path is a sequence of edges, such as the path from vertex B to the vertex J is baej, and of course there are other paths bcdj,bacdj and so on.
③, connected graphs, and non-connected graphs:
If there is at least one path that can connect all the vertices, then the graph is called connected, and if there are no vertices from one vertex to another, it is called non-unicom.
④, forward graphs, and no-show graphs:
If the edges in the diagram do not have a direction and can reach the other side from either side, it is called a non-directed graph, such as a two-way highway, a city to B City can drive from a to B, you can drive from City B to a city. But if you can only sail from city A to the map of City B, then it is called a map.
⑤, power graphs and unauthorized graphs:
The edges in the diagram are given a weight, which is a number that represents the physical distance between the two vertices, or the time from one vertex to another, which is called the Power graph, and the other side has no assigned value, which is called an unauthorized graph.
In this blog we are talking about the right to no map.
2, in the program to show the diagram
We know that the graph is made up of vertices and edges, so how do you simulate vertices and edges in a computer?
①, Vertex:
In most cases, a vertex represents a real-world object that must be described by a data item. For example, in an airplane flight simulator, the vertex represents the city, then it needs to store the city's name, altitude, location and other relevant information, so it usually uses a vertex class object to represent a vertex, where we only store a letter in the vertex to identify the vertex, and there is a flag bit, Used to determine if the vertex has been accessed (for subsequent searches).
/** * Vertex class * @author vae */public class Vertex {public char label;public boolean wasvisited;public Vertex (char label) {this. Label = Label;wasvisited = false;}}
Vertex objects can be placed in an array, then indicated by subscript, or placed in a linked list or other data structure, regardless of the structure used, storage is only for ease of use, which is not related to the edge how to connect points.
②, Edge:
In the previous explanation of the data structure of the various trees, most trees are references to each node that contains its child nodes, such as red-black trees and binary trees. Also useful is the array representation tree, where the position of the node in the tree group determines its relationship to the other nodes, such as the heap is represented by an array.
However, the graph is not like a tree, the graph has no fixed structure, each vertex of the graph can be connected with any number of vertices, in order to simulate this free form of the organization, the following two ways to represent the diagram: adjacency Matrix and adjacency table (if one side joins two vertices, then the two vertices are contiguous)
Adjacency Matrix:
The adjacency matrix is a two-dimensional array, and the data item represents whether there is an edge between two points, and if there are N vertices in the graph, the adjacency matrix is an array of n*n. The adjacency matrix is represented as follows:
1 means there are edges, 0 means no edges, and can be represented by Boolean variables true and False. Vertices are connected to themselves by 0, so the diagonal of the matrix from the upper left to the upper right is 0.
Note: The upper triangle of this matrix is the mirror of the lower triangle, the two triangles contain the same information, this redundant information seems inefficient, but in most computers, it is difficult to create a triangular array, so we have to accept this redundancy, which also requires in the program processing, when we add an edge, For example, update the two parts of the adjacency matrix, not the part.
adjacency table:
An adjacency table is an array of linked lists (or a list of linked lists), and each individual linked list represents which vertices are adjacent to the current vertex.
3. Search
One of the most basic things to do in the diagram is to search for the vertices that can be reached from a specified vertex, such as which cities the high-speed train from Wuhan can reach, some cities that can be reached, and some that cannot be connected directly. Now there is a national high-speed rail simulation diagram, to start from a city (vertex), along the tracks (edge) to other cities (vertices), there are two ways to search for graphs: Depth-First search (DFS) and breadth-first search (BFS). They eventually reach all connected vertices, the depth-first search is implemented through the stack, and the breadth-first search is implemented through queues, and different implementations cause different search methods.
①, Depth-first search (DFS)
The depth-first search algorithm has the following rules:
Rule 1: If possible, access an adjacent unreachable vertex, mark it, and put it on the stack.
Rule 2: When Rule 1 o'clock cannot be executed, if the stack is not empty, a vertex is popped from the stack.
Rule 3: If rule 1 and Rule 2 o'clock are not executed, the entire search process is completed.
For, apply A depth-first search as follows: Assuming that A Vertex is selected as the starting point and is accessed alphabetically, then rule 1 is applied, then the vertex B is accessed, then it is marked and placed on the stack, then rule 1 is applied, then the vertex F is accessed, then rule 1 is applied again, and the vertex H is accessed. We found at this time that there is no H vertex adjacency point, when applying Rule 2, pop from the stack h, the moment back to the vertex F, but we found that F also has no adjacency and no access to the vertex, then the F, this time back to the vertex B, the same rule 1 can not apply, apply Rule 2, Pop B , when there is only vertex a in the stack, then a also has an inaccessible adjacency point, all the next access to the vertex C, but C is the end of the line, so pop it from the stack, go back to a, then access d,g,i, and finally back to a, then access E, but finally back to the vertex a, this time we found a No The adjacency point has not been accessed, so it also pops up the stack. Now that there are no vertices in the stack, rule 3 is applied and the entire search process is completed.
Depth-First search is the ability to find vertices that are contiguous to a vertex and have no access. Here, for example, in the adjacency matrix, find the row where the vertex is located, search backward from the first column for a column with a value of 1, the column number is the number of the adjacency vertex, check if the vertex has not been accessed, and if so, this is the next vertex to access, if the row has no vertices equal to 1 (adjacency) and is Then the vertices adjacent to the specified point are all accessed (and later implemented by the algorithm).
②, Breadth First search (BFS)
The depth-first search should be as far away from the starting point as possible, while the breadth-first search should be as close as possible to the starting point, which first accesses all the adjacency points of the starting vertex and then accesses the farther area, which cannot be implemented with a stack, but is implemented in a queue.
Rule 1: Access the next inaccessible adjacency point (if present), the vertex must be the adjacency point of the current vertex, mark it, and insert it into the queue.
Rule 2: If you do not have an inaccessible adjacency point and cannot execute Rule 1 o'clock, remove a vertex from the queue column header (if one exists) and make it the current vertex.
Rule 3: If rule 2 cannot be executed because the queue is empty, the search ends.
For the above diagram, apply breadth-first search: with a as the starting point, first access all the vertices adjacent to a, and insert them into the queue while accessing, and now have access to a,b,c,d and E. At this point the queue (from beginning to end) contains BCDE, there are no unreachable vertices that are adjacent to vertex A, so take b from the queue and look for the vertices adjacent to B, and F is found, so f is inserted into the queue. There are no vertices that have not been accessed and are adjacent to B, so C is removed from the queue header, and it does not have an inaccessible adjacency point. So take out D and access g,d also have no inaccessible adjacency point, so take out E, now there is FG in the queue, take out F, Access H, then take out G, Access I, now there are HI in the queue, when they are taken out, there is no other vertex for access, when the queue is empty, the search is over.
③, program implementation
Stack stackx.class for deep-first search
Package Com.ys.graph;public class Stackx {private final int SIZE = 20;private int[] st;private int top;public Stackx () {St = New Int[size];top =-1;} public void push (int j) {St[++top] = j;} public int pop () {return st[top--];} public int Peek () {return st[top];} public Boolean isEmpty () {return (top = =-1);}}
Queue Queue.class for breadth-first search
Package Com.ys.graph;public class Queue {private final int SIZE = 20;private int[] quearray;private int front;private int Rear;public Queue () {Quearray = new Int[size];front = 0;rear =-1;} public void Insert (int j) {if (rear = = SIZE-1) {rear =-1;} Quearray[++rear] = j;} public int Remove () {int temp = quearray[front++];if (front = = SIZE) {front = 0;} return temp;} public Boolean isEmpty () {return (rear+1 = = Front | | front+size-1 = = rear);}}
Figure Code Graph.class
Package Com.ys.graph;public class Graph {private final int max_verts = 20;//represents the number of vertices private Vertex vertexlist[];//used to store vertices The group private int adjmat[][];//uses the adjacency matrix to store the edges, the array element 0 means no bounds, and 1 indicates that there is a boundary private int nverts;//vertex number private Stackx thestack;// Use the stack to achieve depth-first search private queue queue;//to achieve breadth-first search/** * Vertex class * @author vae */class Vertex {public char label;public Boolean Wasvis Ited;public Vertex (char label) {This.label = label;wasvisited = false;}} Public Graph () {vertexlist = new Vertex[max_verts];adjmat = new Int[max_verts][max_verts];nverts = 0;//initialization vertex count is 0// Initialize adjacency matrix All elements are 0, that is, all vertices have no edge for (int i = 0; i < max_verts; i++) {for (int j = 0; J < Max_verts; J + +) {Adjmat[i][j] = 0;}} Thestack = new Stackx (); queue = new Queue ();} Adds a vertex to the array, whether the access flag is set to Wasvisited=false (not accessed) public void Addvertex (char lab) {vertexlist[nverts++] = new Vertex (Lab); Note that the adjacency matrix represents the edge, is symmetric, and both parts are assigned the public void Addedge (int start, int end) {Adjmat[start][end] = 1;adjmat[end][start] = 1;} Prints the value represented by a vertex public void Displayvertex (int v) {System.out.print (vertexlist[V].label);} /** Depth-First search algorithm: * 1, using Peek () method to check the top of the stack * 2, using the Getadjunvisitedvertex () method to find the current stack vertex adjacency and not accessed vertex * 3, the second step method return value not equal to 1 find the next unreachable adjacency Vertex, Access this vertex, into the stack * If the second step method returns a value equal to-1, then not found, out of the stack */public void Depthfirstsearch () {//starting from the first vertex access vertexlist[0].wasvisited = true;//visit After the question is marked Truedisplayvertex (0);//The first vertex of the print access Thestack.push (0);//Put the first vertex in the stack while (!thestack.isempty ()) {// Locate the current vertex adjacency of the stack and the unreachable vertex int v = Getadjunvisitedvertex (Thestack.peek ()), if (v = =-1) {///If the current vertex value is-1, the vertex is not contiguous and is not accessed. Then the stack vertex thestack.pop ();} else {//otherwise access the next adjacency vertex vertexlist[v].wasvisited = True;displayvertex (v); Thestack.push (v);}} Stack access complete, reset all marker bits wasvisited=falsefor (int i = 0; i < nverts; i++) {vertexlist[i].wasvisited = false;}} Locates a vertex that is adjacent to a vertex and is not accessed public int Getadjunvisitedvertex (int v) {for (int i = 0; i < nverts; i++) {//v vertex is adjacent to the I vertex (adjacency matrix value is 1) and is not accessed Wasvisited==falseif (Adjmat[v][i] = = 1 && vertexlist[i].wasvisited = = False) {return i;}} return-1;} /** * Breadth-First search algorithm: * 1, check the top vertex of the stack with the Remove () method * 2, try to find the vertex has not visited the neighbor * 3, if not found, the vertex out of * 4, if you find such a vertex, access to the vertex, and put it into the queue */public void Breadthfirstsearch () {vertexlist[0].wasvisited = True;displayvertex (0); Queue.insert (0); int v2;while (! Queue.isempty ()) {int v1 = Queue.remove (); while ((v2 = Getadjunvisitedvertex (v1))! =-1) {vertexlist[v2].wasvisited = True ;d Isplayvertex (v2); Queue.insert (v2);}} Search complete, initialize, for the next search for (int i = 0; i < nverts; i++) {vertexlist[i].wasvisited = false;}} public static void Main (string[] args) {Graph graph = new Graph (); Graph.addvertex (' A '); Graph.addvertex (' B '); Graph.addvertex (' C '); Graph.addvertex (' D '); Graph.addvertex (' E '); Graph.addedge (0, 1);//abgraph.addedge (1, 2);// Bcgraph.addedge (0, 3);//adgraph.addedge (3, 4);//desystem.out.println ("depth-first search algorithm:"); Graph.depthfirstsearch ();// ABCDESystem.out.println (); System.out.println ("----------------------"); System.out.println ("Breadth-first search algorithm:"); Graph.breadthfirstsearch ();//abdce}}
Test results:
4. Minimum spanning tree
One of the most common things to do with graphs is to find the smallest spanning tree, which is to connect all vertices with the fewest edges. There may be a number of minimum spanning trees for a given set of vertices, but the number of edges of the smallest spanning tree is always 1 smaller than the number of vertex V, which is:
V = E + 1
There is no need to worry about the length of the side, not the shortest path (which will be explained in the weighted graph), but rather a minimum number of edges, which can be achieved based on depth-first search and breadth-first search.
For example, based on depth-first search, we can create a minimal spanning tree by recording the edges we have traversed. Because DFS accesses all vertices, but only once, it never accesses the same vertex two times, but she sees that an edge will reach a vertex that has been visited, it will not go that edge, it never traverses those impossible edges, so the path of the DFS algorithm across the graph must be the smallest spanning tree.
Find minimum spanning tree public void MST () {vertexlist[0].wasvisited = True;thestack.push (0) based on depth-first search, while (!thestack.isempty ()) {int Currentvertex = Thestack.peek (); int v = Getadjunvisitedvertex (Currentvertex); if (v = =-1) {Thestack.pop ();} else{vertexlist[v].wasvisited = True;thestack.push (v);d Isplayvertex (Currentvertex);d Isplayvertex (v); System.out.print ("");}} Search complete, initialize, for the next search for (int i = 0; i < nverts; i++) {vertexlist[i].wasvisited = false;}}
5. Summary
The graph is made up of vertices connected by edges, which can represent many real world situations, including aircraft routes, electronic circuits, and so on. The search algorithm accesses each vertex in the graph in a systematic way, mainly through depth-first search (DFS) and breadth-first search (BFS), and depth-first search through the stack, and breadth-first search is implemented through the queue. Finally, you need to know that the minimum spanning tree is the minimum number of edges required to contain all the vertices in the join diagram.
Java Data structures and algorithms (15)--no permission graph