1, The storage method of the graph. If the graph is expressed, the graph is generated

1. Storage mode of drawing  2. Expression of graph - point set, edge set, graph

• point set
public class Node {
public int value;
public int in; //Penetration
public int out; //Out degree
public ArrayList<Node> nexts;  //The point of a direct neighbor diverged by him
public ArrayList<Edge> edges;  //What are my sides

public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
• Edge set
public class Edge {
public int weight; //weight
public Node from;  //Directed edge from
public Node to;  //Directed edge to

public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}

}
• Figure: Point Set + edge set
public class Graph {
public HashMap<Integer,Node> nodes; // The Integer here represents a marker value of the point that appears
public HashSet<Edge> edges;  //Edge set

public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}

3. Generate diagram

• Two dimensional array, in which the first item of each array represents the weight and the second item represents from. The third item indicates to
public static Graph createGraph(Integer[][] matrix) {
Graph graph = new Graph();
//The outermost loop represents several large loops, one one-dimensional array and one edge at a time
for (int i = 0; i < matrix.length; i++) {
//The first item in each array represents the weight
Integer weight = matrix[i];
//The second item indicates where from comes from
Integer from = matrix[i];
//The third item indicates where to points
Integer to = matrix[i];
//Judge this first. If not, skip it
//If the from point does not exist in the point set of the graph, add the point to the point set
//Update of point set of graph
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));//join
}
//If the to point does not exist in the point set of the graph, add the point to the point set
if (!graph.nodes.containsKey(to)) {
graph.nodes.put(to, new Node(to));//join
}
//Get the from point and the to point
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
//The edges are established by these two points and weights
Edge newEdge = new Edge(weight, fromNode, toNode);
//Next, you need to update: points, edges and graphs should be updated
//Update the nexts of fromnode's points, that is, the points of direct neighbors diverged by him
//Update the out of the fromnode point, that is, the out degree++
fromNode.out++;
//Update the in of the point of tonode, that is, the penetration++
toNode.in++;
//Update the edges of fromnode, that is, update the edges belonging to fromnode. This is to add a newly created edge
//Graph update, add one more edge set
}
return graph;
}

2, Traversal of Graphs

1. The width of the drawing shall first traverse the BFS

Using queues to implement
Enter the queue according to the width from the source node, and then pop up;
For each pop-up point, put all adjacent points of the node that have not entered the queue into the queue;
Until the queue is empty.

//Only point set type is needed
public void BFS_(Node node){
if(node == null){
return;
}
//Prepare a queue to pop up by width in turn
//Prepare a set set for de duplication to prevent a node from being added to the queue repeatedly, and finally output such errors repeatedly
HashSet<Object> hashset = new HashSet<>();
//First add the source node to set and queue
//If the queue is not empty, it pops up one by one
while(!queue.isEmpty()){
Node cur = queue.poll();
//Output on pop-up
System.out.println(cur.value);
//During each pop-up, all adjacent nodes of the pop-up node and nodes that have not entered the set are added to the queue.
for(Node next:cur.nexts){
if(!hashset.contains(next)){
}
}
}
}

2. The depth of the graph first traverses DFS

Depth first traversal: starting from the initial access point, the initial access point may have multiple adjacent nodes. The strategy of depth first traversal is to first access the first adjacent node, and then use the accessed adjacent node as the initial access node to access its first adjacent node, That is, each time the current node is accessed, the first adjacent node of the current node will be accessed first. Similar to maze backtracking algorithm.
It can be seen that the current access strategy is to give priority to vertical mining, rather than horizontal access to all adjacent points of each node.

Using stack
A single wooden bridge goes to the black
Start from the source node, put each node into the stack according to the depth, and then pop up;
For each pop-up point, put the next adjacent point of the node that has not entered the stack into the stack;
Until the stack becomes empty.

HashSet<Node> hashset = new HashSet<>();
Stack<Node> stack = new Stack<>();
stack.push(node);
System.out.println(node.value);
while(!stack.isEmpty()){
Node cur = stack.pop();
for(Node next : cur.nexts){
if(!hashset.contains(next)){
//Note here that cur itself should also be added. Why? This gives a way back to prevent the next encounter from already in the set, so we have to find a way back, that is, backtracking and find other nodes.
stack.push(cur);
stack.push(next);
System.out.println(next.value);
//The reason for breaking is to let him not follow the width, but encounter a cycle of breaking this time, and let him continue down the new node. If he doesn't break, go to the width.
break;
}
}
}
} 3, Topological sorting algorithm

Scope of application: it is required to have a directed graph, nodes with penetration of 0, and no ring
Topological sorting is actually to find a vertex with a degree of 0. This vertex is the first vertex sequence in topological sorting, mark and delete it, then reduce the degree of entry of the vertex adjacent to this vertex by 1, and then continue to find the vertex with a degree of 0 until all vertices have been marked and deleted or there are rings in the graph.
It can be seen from the above that the key is to find the vertex with penetration of 0.

Dependency completion sort
Directed graph
Using hash table
Find the points with penetration of 0 in turn, wipe them off in turn, and find them again in turn public static List<Node> sortTopology(Graph graph){
//K of hashmap represents a node, and V represents the remaining penetration
HashMap<Node, Integer> hashMap = new HashMap<>();
//Points with 0 remaining in the queue enter the queue
for (Node node : graph.nodes.values()){
hashMap.put(node, node.in); // Record the original penetration
if (node.in == 0){ // The first batch of click in queues with a penetration of 0
}
}
//The topology sorting results are placed in the result
List<Node> result = new ArrayList<>();
while ( !zeroInQueue.isEmpty()){
Node cur = zeroInQueue.poll();
//Erase the influence of the current node
for (Node next : cur.nexts){
hashMap.put(next,hashMap.get(next) - 1); //Penetration is wiped
if (hashMap.get(next) == 0){
}
}
}
return result;
}

4, Two algorithms of minimum spanning tree

Minimum spanning tree = = = guaranteed connectivity, minimum weight, for undirected graph

1.Kruskal algorithm

Scope of application: undirected graph is required

• Algorithm overview

Kruskal algorithm can be referred to as "edge addition method".
1) Always start from the edge with the smallest weight and investigate the edge with the larger weight in turn
2) The current edge either enters the collection of the minimum spanning tree or is discarded
3) If the current edge enters the set of the minimum spanning tree and does not form a ring, the current edge is selected
4) If the current edge enters the set of the minimum spanning tree to form a ring, do not use the current edge
5) After examining all the edges, the set of the minimum spanning tree is also obtained.

• sketch 1) To sort the edges, start from the smallest edge and judge whether there is an invisible ring (and search the set). If it is formed, it will not be added, and if it is not formed, it will be added
2) The judgment has an invisible ring, and all the initial points have a set respectively, which can be combined if possible.
3) Set query and merge - > join query set or common method

• Common method
public static class Mysets{

public HashMap<Node, List<Node>> setMap;//map of the collection of points

public Mysets(List<Node> nodes){
for (Node cur: nodes){
List<Node> set = new ArrayList<>(); // Collection of each point
set.add(cur); //The collection of each point is its own at the beginning
setMap.put(cur,set);
}
}

//Are from and to in the same set
public boolean isSameSet(Node from, Node to){
List<Node> fromSet = setMap.get(from); //Collection from
List<Node> toSet = setMap.get(to); //Set of to
return fromSet == toSet; //Judge whether it is a set
}

//Synthesis of two sets
public void union(Node from, Node to){
List<Node> fromSet = setMap.get(from); //Collection from
List<Node> toSet = setMap.get(to); //Set of to
for (Node toNode : toSet){
setMap.put(toNode,fromSet);
}
}
}
//K algorithm
public static Set<Edge> kruskalMST(Graph graph){
Mysets mysets = new Mysets((List<Node>) graph.nodes.values());
//At the bottom of the priority queue is the heap
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new Comparator<Edge>() {
@Override
public int compare(Edge o1, Edge o2) {
return o1.weight - o2.weight;
}
});
for (Edge edge : graph.edges){
}
Set<Edge> result = new HashSet<>();
while ( !priorityQueue.isEmpty()){
Edge edge = priorityQueue.poll();
if ( !mysets.isSameSet(edge.from, edge.to)){
mysets.union(edge.from, edge.to);
}
}
return result;
}
• Use and query set
// Union-Find Set
public static class UnionFind {
private HashMap<Node, Node> fatherMap;
private HashMap<Node, Integer> rankMap;

public UnionFind() {
fatherMap = new HashMap<Node, Node>();
rankMap = new HashMap<Node, Integer>();
}

private Node findFather(Node n) {
Node father = fatherMap.get(n);
if (father != n) {
father = findFather(father);
}
fatherMap.put(n, father);
return father;
}

public void makeSets(Collection<Node> nodes) {
fatherMap.clear();
rankMap.clear();
for (Node node : nodes) {
fatherMap.put(node, node);
rankMap.put(node, 1);
}
}

public boolean isSameSet(Node a, Node b) {
return findFather(a) == findFather(b);
}

public void union(Node a, Node b) {
if (a == null || b == null) {
return;
}
Node aFather = findFather(a);
Node bFather = findFather(b);
if (aFather != bFather) {
int aFrank = rankMap.get(aFather);
int bFrank = rankMap.get(bFather);
if (aFrank <= bFrank) {
fatherMap.put(aFather, bFather);
rankMap.put(bFather, aFrank + bFrank);
} else {
fatherMap.put(bFather, aFather);
rankMap.put(aFather, aFrank + bFrank);
}
}
}
}

public static class EdgeComparator implements Comparator<Edge> {

@Override
public int compare(Edge o1, Edge o2) {
return o1.weight - o2.weight;
}

}

public static Set<Edge> kruskalMST(Graph graph) {
UnionFind unionFind = new UnionFind();
unionFind.makeSets(graph.nodes.values());
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator());
for (Edge edge : graph.edges) {
}
Set<Edge> result = new HashSet<>();
while (!priorityQueue.isEmpty()) {
Edge edge = priorityQueue.poll();
if (!unionFind.isSameSet(edge.from, edge.to)) {
unionFind.union(edge.from, edge.to);
}
}
return result;
}

2.Prim algorithm

Scope of application: undirected graph is required
Starting from the point, find the smallest edge, so as to get the point and start again and again

public static class EdgeComparator implements Comparator<Edge>{
@Override
public int compare(Edge o1, Edge o2) {
return o1.weight - o2.weight;
}
}
public static Set<Edge> primSet(Graph graph){
//The unlocked edge enters the small root heap
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator());
HashSet<Node> set = new HashSet<>(); //The unlocked points are placed in the set
Set<Edge> result = new HashSet<>(); //Select the edges in turn and put them into result
//The for loop handles the forest problem and generates the minimum spanning tree respectively. This is a special case. If the whole is a connected graph, there is no need to add it here
for (Node node : graph.nodes.values()){//Pick any point
//node is the starting point
if ( !set.contains(node)){
for (Edge edge : node.edgs){ //By one point, unlock all connected edges
}
while ( !priorityQueue.isEmpty()){
Edge edge = priorityQueue.poll(); //The smallest of the pop-up unlocked edges
Node toNode = edge.to;
//Judge whether the toNode is a new point or not in the set
if ( !set.contains(toNode)){ //No, just a new point, just join
//I want this side
//The edges diverged from the toNode are put into the priority queue
for (Edge nextEdge : toNode.edgs){