class6
- 图的存储方式
1)邻接表
2)邻接矩阵
package com.godzuo.java;
import java.util.HashMap;
import java.util.HashSet;
/**
* @author quanquan
* @create 2020-05-03-20:40
*/
public class Graph {
public HashMap<Integer,Node> nodes;
public HashSet<Edge> edges;
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
package com.godzuo.java;
import java.util.ArrayList;
public class Node {
public int value;
public int in;
public int out;
public ArrayList<Node> nexts;
public ArrayList<Edge> edges;
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
package com.godzuo.java;
public class Edge {
public int weight;
public Node from;
public Node to;
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
package com.godzuo.java;
/**
* 生成图
*/
public class GraphGenerator {
public static Graph createGraph(Integer[][] matrix) {
Graph graph = new Graph();
for (int i = 0; i < matrix.length; i++) {
Integer weight = matrix[i][0];
Integer from = matrix[i][1];
Integer to = matrix[i][2];
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}
if (!graph.nodes.containsKey(to)) {
graph.nodes.put(to, new Node(to));
}
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
Edge newEdge = new Edge(weight, fromNode, toNode);
fromNode.nexts.add(toNode);
fromNode.out++;
toNode.in++;
fromNode.edges.add(newEdge);
graph.edges.add(newEdge);
}
return graph;
}
}
-
-
广度(宽度)优先遍历
1,利用队列实现
2,从源节点开始依次按照宽度进队列,然后弹出
3,每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
4,直到队列变空
-
深度优先遍历
1,利用栈实现
2,从源节点开始把节点按照深度放入栈,然后弹出
3,每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈
4,直到栈变空
-
package com.godzuo.java;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
/**
* @author quanquan
* @create 2020-05-03-21:30
*/
public class BFS {
public static void bfs(Node node){
if (node == null){
return;
}
Queue<Node> queue = new LinkedList<>();
HashSet<Node> map = new HashSet<>();
queue.add(node);
map.add(node);
while (!queue.isEmpty()){
Node cur = queue.poll();
System.out.println(cur.value);
for (Node next: cur.nexts){
if(!map.contains(next)){
map.add(next);
queue.add(next);
}
}
}
}
}
package com.godzuo.java;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
/**
* @author quanquan
* @create 2020-05-03-21:49
*/
public class DFS {
public static void dfs(Node node){
if (node == null){
return;
}
Stack<Node> stack = new Stack<>();
HashSet<Node> set = new HashSet<>();
stack.add(node);
set.add(node);
System.out.println(node.value);
while (!stack.isEmpty()){
Node cur = stack.pop();
for (Node next: cur.nexts){
if (!set.contains(next)){
stack.push(cur);
stack.push(next);
set.add(next);
System.out.println(next.value);
break;
}
}
}
}
}
-
拓扑排序算法(做到自己时,依赖条件都已做完)
适用范围:要求有向图,且有入度为0的节点,且没有环
package com.godzuo.java;
import java.util.*;
/**
* @author quanquan
* @create 2020-05-03-22:24
*/
public class TopologySort {
// directed graph and no loop
public static List<Node> sortedTopology(Graph graph){
HashMap<Node, Integer> inMap = new HashMap<>();
Queue<Node> zeroInQue = new LinkedList<>();
for (Node node : graph.nodes.values()){ //遍历所有的点
inMap.put(node, node.in);
if (node.in == 0){
zeroInQue.add(node);
}
}
List<Node> result = new ArrayList<>();
while (!zeroInQue.isEmpty()){
Node cur = zeroInQue.poll();
result.add(cur);
for (Node next : cur.nexts){
inMap.put(next,inMap.get(next)-1);
if (inMap.get(next) == 0){
zeroInQue.add(next);
}
}
}
return result;
}
}
-
最小生成树算法(要求:无向图):kruskal算法 和 prim算法
- kruskal算法:从小权重的边开始考察
package com.godzuo.java; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.PriorityQueue; import java.util.Set; //undirected graph only public class Kruskal { // 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) { priorityQueue.add(edge); } Set<Edge> result = new HashSet<>(); while (!priorityQueue.isEmpty()) { Edge edge = priorityQueue.poll(); if (!unionFind.isSameSet(edge.from, edge.to)) { result.add(edge); unionFind.union(edge.from, edge.to); } } return result; } }
- prim算法:按照点来考察
package com.godzuo.java; import java.security.PublicKey; import java.util.*; /** * @author quanquan * @create 2020-05-03-23:37 */ public class Prim { public static class EdgeComparator implements Comparator<Edge> { @Override public int compare(Edge o1, Edge o2) { return o1.weight - o2.weight; } } public static Set<Edge> primMST(Graph graph) { PriorityQueue<Edge> priorityQueue = new PriorityQueue<>( new EdgeComparator()); HashSet<Node> set = new HashSet<>(); Set<Edge> result = new HashSet<>(); for (Node node : graph.nodes.values()) { //若输入的图为森林,则有多个生成树 if (!set.contains(node)) { set.add(node); for (Edge edge : node.edges) { priorityQueue.add(edge); } while (!priorityQueue.isEmpty()) { Edge edge = priorityQueue.poll(); Node toNode = edge.to; if (!set.contains(toNode)) { set.add(toNode); result.add(edge); for (Edge nextEdge : toNode.edges) { priorityQueue.add(nextEdge); } } } } } return result; } }
-
最短路径算法
- Dijkstra算法 适用范围:没有权值为负数的边