10 commonly used algorithms (8 ~ 10)
1, Dijkstra algorithm
Application scenario - shortest path problem
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-g8rjj2vk-1645791772844) (C: \ users \ Luo'xin \ appdata \ roaming \ typora \ typora user images \ image-20220223143121774. PNG)]
This graph is the same as the graph of the previous two algorithms. The first two algorithms are to find the minimum spanning tree of a graph, while dijestra algorithm is to find the minimum path from a point to other vertices in a graph.
The idea of dijestra algorithm is recommended Blog Simple and vivid.
From the above blog, we can know that the steps of dijestra algorithm are as follows:
- Two sets U and S. initially, U stores other points in the graph except the starting point, and each point has A value. This value is the minimum path of the point through the s graph and the starting point. For example, if A is the starting point, the weight of B is 5 and the weight of D is infinite (because it cannot be reached through s), S stores the starting point, and each point in s also has A weight, Represents the minimum path from this point to the starting point, that is, what we need.
- Select a point with the smallest weight from u, delete it from u and add it to S set. The weight is the original weight in U.
- Update the weights of other points in the U set. Because points are added to S, the previously unreachable points in u may also be reached, or some points can have a shorter arrival path, so they need to be updated.
- Then cycle until the U set is empty. Finally, the weight of each point in the S set is the minimum path from the point to the starting point.
The above operations are relatively simple, except for updating the set weight. We can find that all the points to update the weight are actually the direct connection points of the selected points. For the update operation, we only need to obtain the direct connection points of the deleted points first, and then compare the original weight with the weight from itself to the deleted points + the weight of the deleted points one by one, If the weight from itself to the deleted point + the weight of the deleted point is less than the original weight, it will be updated, otherwise it will not be updated.
My own code is as follows:
/** * @author: luoxin * @create: 2022-02-23 11:39 **/ package cn.luoxin88.algorithm.dijkstra; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; public class DijkstraAlgorithm { public static void main(String[] args) { char[] data = {'A','B','C','D','E','F','G'}; int[][] weight = {{10000,5,7,10000,10000,10000,2}, {5,10000,10000,9,10000,10000,3}, {7,10000,10000,10000,8,10000,10000}, {10000,9,10000,10000,10000,4,10000}, {10000,10000,8,10000,10000,5,4}, {10000,10000,10000,4,5,10000,6}, {2,3,10000,10000,4,6,10000}}; MGragh gragh = new MGragh(data, weight); DijkstraAlgorithm dijkstraAlgorithm = new DijkstraAlgorithm(); HashSet<Verx> set = dijkstraAlgorithm.dijkstra(gragh,0); System.out.println(set); } public HashSet<Verx> dijkstra(MGragh gragh, int index) { //Two sets HashSet<Verx> oldSet = new HashSet<>(); HashSet<Verx> newSet = new HashSet<>(); //Collection initialization for(int i=0;i< gragh.verx;i++) { if(i!=index) { oldSet.add(new Verx(i,gragh.weight[i][index])); } } newSet.add(new Verx(index,0)); System.out.println("original old : "+oldSet); System.out.println("original new : "+newSet); //Loop values continuously until the original set is empty Verx temp, object = null; while(!oldSet.isEmpty()) { //Select a vertex with the smallest weight from the original set int minValue = 10000; Iterator<Verx> iterator = oldSet.iterator(); //Gets the minimum point of the current collection while(iterator.hasNext()) { temp = iterator.next(); if(temp.value<minValue) { minValue = temp.value; object = temp; } } //Delete from the original set and add to the new set oldSet.remove(object); newSet.add(object); //Update the weight of each vertex of the original set fresh(oldSet, gragh, object); System.out.println("old : "+oldSet); System.out.println("new: "+newSet); } return newSet; } public void fresh(HashSet<Verx> set, MGragh gragh, Verx verx) { //Find each vertex directly connected to verx, and then compare the original weight with (distance to verx + verx weight) Iterator<Verx> iterator = set.iterator(); Verx temp = null; while(iterator.hasNext()) { temp = iterator.next(); //In case of direct connection if(gragh.weight[temp.index][verx.index] != 10000) { //If (distance to verx + verx weight) is the original weight, update it if(( gragh.weight[temp.index][verx.index]+ verx.value) < temp.value) { //Note that the following methods cannot be used. It is not allowed to add or delete the original set directly during iterator iteration //Otherwise, an error of ConcurrentModificationException will be reported //set.remove(temp); //set.add(new Verx(temp.index, ( gragh.weight[temp.index][verx.index]+ verx.value))); temp.value = ( gragh.weight[temp.index][verx.index]+ verx.value); } } } } } class Verx { int index; int value; public Verx(int index,int value) { this.index = index; this.value = value; } char[] arr = {'A','B','C','D','E','F','G'}; @Override public String toString() { return "[" + "index=" + arr[index] + ", value=" + value + ']'; } } class MGragh { int verx;//Represents the number of nodes in the graph char[] data ;//Store node data int[][] weight;//The storage edge is our adjacency matrix public MGragh(int verx) { data = new char[verx]; weight = new int[verx][verx]; } public MGragh(char[] data, int[][] weight) { this.verx = data.length; this.data = new char[this.verx]; this.weight = new int[this.verx][this.verx]; int i,j; for (i=0;i<this.verx;i++) { this.data[i] = data[i]; for(j=0;j<verx;j++) { this.weight[i][j] = weight[i][j]; } } } public static void showGragh(MGragh gragh) { for(int[] row : gragh.weight) { System.out.println(Arrays.toString(row)); } } }
The process is as follows:
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-XWfM72d0-1645791772846)(C:\Users\luo'xin \ appdata \ roaming \ typora \ typora user images \ image-20220224083212478. PNG)]
We can see that it is the same as we expected.
2, Freudian algorithm
1 . Introduction to Floyd algorithm
Like Dijkstra algorithm, Floyd algorithm is also used to find the shortest path between vertices in a given weighted graph.
Dijkstra algorithm calculates the shortest path from one vertex to other vertices in the graph, while Floyd algorithm calculates the shortest path between each vertex in the graph.
2 . Floyd's problem solving ideas
Floyd algorithm solution ideas recommended Blog , be patient and easy to understand.
Let me also briefly say that at the beginning, a two-dimensional matrix is used to store the distance between each point, which cannot be directly reached as infinity.
We need to constantly update this matrix so that M [i] [j] in the final matrix is the shortest distance between I and j.
How to update?
We know that the shortest path between two points is no more than two cases:
- There is a direct connection between the two points
- The two points are not directly connected and need to be connected through other points
The initial matrix lists the distance between all directly connected vertices. Of course, this distance may not be the shortest distance, because it is possible that the distance through other points will be shorter than that between directly connected points.
So we need to know whether the distance after passing through the direct connection point will be shorter than the current distance. There are many possibilities for the number of direct connection points. Let's consider the case of a direct connection point first. We might as well set the direct connection point to 1 (subscript). We need to judge whether any I, j is weight [i] [J] > weight [i] [1] + weight [1] [J]. Updates if the value after passing the vertex is smaller.
for(i=0;i<verx;i++) { for(j=0;j<verx;j++) { if(gragh.weight[i][j] > (gragh.weight[i][1] + gragh.weight[1][j])) { gragh.weight[i][j] = (gragh.weight[i][1] + gragh.weight[1][j]); } } }
After the update, we should consider the case of passing through two vertices. How to see two vertices? It's very simple. Just add another vertex on the original basis, because we have judged 1 before. Let's judge another 2,
for(i=0;i<verx;i++) { for(j=0;j<verx;j++) { if(gragh.weight[i][j] > (gragh.weight[i][2] + gragh.weight[2][j])) { gragh.weight[i][j] = (gragh.weight[i][2] + gragh.weight[2][j]); } } }
In fact, this process is somewhat similar to the previous Dijkstra algorithm.
If you can understand from 1 to 2, the whole algorithm is easy to say. See below.
public void floyd(MGragh gragh) { int verx = gragh.verx; int i,j,k; for(k=0;k<verx;k++) { for(i=0;i<verx;i++) { for(j=0;j<verx;j++) { if(gragh.weight[i][j] > (gragh.weight[i][k] + gragh.weight[k][j])) { gragh.weight[i][j] = (gragh.weight[i][k] + gragh.weight[k][j]); } } } } }
Yes, it's that simple.
3 . Floyd algorithm code
import java.util.Arrays; public class FloydAlgorithm { public static void main(String[] args) { char[] data = {'A','B','C','D','E','F','G'}; int[][] weight = {{10000,5,7,10000,10000,10000,2}, {5,10000,10000,9,10000,10000,3}, {7,10000,10000,10000,8,10000,10000}, {10000,9,10000,10000,10000,4,10000}, {10000,10000,8,10000,10000,5,4}, {10000,10000,10000,4,5,10000,6}, {2,3,10000,10000,4,6,10000}}; MGragh gragh = new MGragh(data, weight); gragh.showGragh(gragh); FloydAlgorithm floydAlgorithm = new FloydAlgorithm(); floydAlgorithm.floyd(gragh); MGragh.showGragh(gragh); } public void floyd(MGragh gragh) { int verx = gragh.verx; int i,j,k; for(k=0;k<verx;k++) { for(i=0;i<verx;i++) { for(j=0;j<verx;j++) { if(gragh.weight[i][j] > (gragh.weight[i][k] + gragh.weight[k][j])) { gragh.weight[i][j] = (gragh.weight[i][k] + gragh.weight[k][j]); } } } } } } class MGragh { int verx;//Represents the number of nodes in the graph char[] data ;//Store node data int[][] weight;//The storage edge is our adjacency matrix public MGragh(int verx) { data = new char[verx]; weight = new int[verx][verx]; } public MGragh(char[] data, int[][] weight) { this.verx = data.length; this.data = new char[this.verx]; this.weight = new int[this.verx][this.verx]; int i,j; for (i=0;i<this.verx;i++) { this.data[i] = data[i]; for(j=0;j<verx;j++) { this.weight[i][j] = weight[i][j]; } } } public static void showGragh(MGragh gragh) { for(int[] row : gragh.weight) { System.out.println(Arrays.toString(row)); } } }
3, Horse Treading chessboard algorithm
1 . Introduction to horse stepping on chessboard algorithm
The horse stepping on the chessboard algorithm is also called the knight traveling problem. It is about randomly placing the horse in a square of the 8x8 international chessboard and moving the horse with the word "day" (2x3). It is required that each chessboard only walk once and walk through all 64 squares on the chessboard.
2 . Explanation of horse stepping on chessboard algorithm
We can easily think of using the depth of the graph to traverse the problem first.
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ggpgz7Ib-1645791772848)(C:\Users\luo'xin \ appdata \ roaming \ typora \ user images \ image-20224202846654. PNG)]
You can see that if the current position is (X,Y), the next step is
- (X-2,Y-1)
- (X-1,Y-2)
- (X+1,Y-2)
- (X+2,Y-1)
- (X+2,Y+1)
- (X+1,Y+2)
- (X-1,Y+2)
- (X-2,Y+1)
When we get to a position
- Mark the position with the corresponding number of steps first
- Mark the corresponding location as accessed
- Judge the other 8 positions. If they are in the chessboard and are not accessed, access (recursion)
- If the eight positions are judged, there is no way to go. At this time, there are two situations
- If the number of steps is the size of the chessboard, it means that all traversal is completed, and set the flag bit finished to true
- Otherwise, it means that it has not been traversed and should be rolled back. Set the number of steps in this cell to 0 and mark the corresponding position as not accessed
3 . Horse Treading chessboard algorithm code implementation
import java.util.Arrays; public class Mataqp { public static final int LENGTH = 8; //Flag bit, indicating whether the traversal is completed private static boolean finished = false; //Identifies which locations on the chessboard have been accessed private int[][] visited = new int[LENGTH][LENGTH]; public static void main(String[] args) { Mataqp mataqp = new Mataqp(); mataqp.mataqp(0,0); System.out.println(1); } public void mataqp(int x, int y) { MGragh gragh = new MGragh(LENGTH); for(int[] rows : gragh.weight) { System.out.println(Arrays.toString(rows)); } int count = 1; System.out.println("-------------------------------"); resoulv(x,y, gragh.weight,count); for(int[] rows : gragh.weight) { System.out.println(Arrays.toString(rows)); } } public void resoulv(int x, int y, int[][] weight, int count) { //Set the value of the current position as the step value weight[x][y] = count; visited[x][y] = 1; //System.out.println("weight["+x+"]["+y+"] = "+count); //The rationality of the eight positions is judged and recursive //If the point is in the chessboard and is not traversed, it is recursive if(inner(x-2,y-1, LENGTH) && weight[x-2][y-1]==0) { resoulv(x-2, y-1, weight, count+1); } if(inner(x-1,y-2, LENGTH) && weight[x-1][y-2]==0) { resoulv(x-1, y-2, weight, count+1); } if(inner(x+1,y-2, LENGTH) && weight[x+1][y-2]==0) { resoulv(x+1, y-2, weight, count+1); } if(inner(x+2,y-1, LENGTH) && weight[x+2][y-1]==0) { resoulv(x+2, y-1, weight, count+1); } if(inner(x+2,y+1, LENGTH) && weight[x+2][y+1]==0) { resoulv(x+2, y+1, weight, count+1); } if(inner(x+1,y+2, LENGTH) && weight[x+1][y+2]==0) { resoulv(x+1, y+2, weight, count+1); } if(inner(x-1,y+2, LENGTH) && weight[x-1][y+2]==0) { resoulv(x-1, y+2, weight, count+1); } if(inner(x-2,y+1, LENGTH) && weight[x-2][y+1]==0) { resoulv(x-2, y+1, weight, count+1); } //None of them. Undo. Go back to the next level //All eight steps have been completed and not completed, indicating that this road is impassable. Take a step back if(count != LENGTH * LENGTH && !finished) { weight[x][y] = 0; visited[x][y]=0; } else { finished = true; } } public boolean inner(int x, int y, int size) { if(x<size && x>=0 && y <size && y>=0) return true; return false; } } class Point { int x,y; public Point() { } public Point(int x, int y) { this.x = x; this.y = y; } @Override public String toString() { return "<"+x+", "+y+">"; } } class MGragh { int verx;//Represents the number of nodes in the graph char[] data ;//Store node data int[][] weight;//The storage edge is our adjacency matrix public MGragh(int verx) { this.verx = verx; data = new char[verx]; weight = new int[verx][verx]; } public MGragh(char[] data, int[][] weight) { this.verx = data.length; this.data = new char[this.verx]; this.weight = new int[this.verx][this.verx]; int i,j; for (i=0;i<this.verx;i++) { this.data[i] = data[i]; for(j=0;j<verx;j++) { this.weight[i][j] = weight[i][j]; } } } public static void showGragh(MGragh gragh) { for(int[] row : gragh.weight) { System.out.println(Arrays.toString(row)); } } }
4 . Efficiency optimization of Horse Treading chessboard algorithm
Although the previous method can achieve results, the efficiency is very low. The reason is that each recursion is carried out mechanically in the order of 8 positions, which is like a blind collision in one direction. Can we have selective recursion? Every recursion starts at the position where it is most likely to complete the whole process.
If in a position, its next step can have five ways. Can we know which of the five walking methods is more likely to finish? Obviously not, so we think every walking method has a 1 / 5 chance to finish. How can we optimize it? If there are five paths now, tell you that the length is 100.200.300.400.500 meters respectively, there are treasures at the end of the path, and the efficiency of each path with treasures is the same, how would you go? Obviously, it's the same here. We have to take the least position in the next step.
So we can't judge and traverse one by one as before. We have to put all the possibilities in a list and sort them in ascending order. Recursion recurses from small to large.
System.out.println(Arrays.toString(row));
}
}
}
### 4 . Efficiency optimization of Horse Treading chessboard algorithm Although the previous method can achieve results, the efficiency is very low. The reason is that each recursion is carried out mechanically in the order of 8 positions, which is like a blind collision in one direction. Can we have selective recursion? Every recursion starts at the position where it is most likely to complete the whole process. If in a position, its next step can have five ways. Can we know which of the five walking methods is more likely to finish? Obviously not, so we think every walking method has 1/5 The possibility is over. How can we optimize it? If there are five paths now, I'll tell you the length is 100 respectively.200.300.400.500 M, there are treasures at the end of the path. The efficiency of each path with treasures is the same. How will you go? Obviously, it's the same here. We have to take the least position in the next step. So we can't judge and traverse one by one as before. We have to put all the possibilities in a list and sort them in ascending order. Recursion recurses from small to large.