P7 图
图的存储形式
- 邻接表
- 邻接矩阵
public class Graph {
Map<Integer, Node> nodes;
List<Edge> edges;
Graph() {
}
Graph(Map<Integer, Node> nodes, List<Edge> edges) {
this.nodes = nodes;
this.edges = edges;
}
}
public class Edge {
int from;
int to;
int weight;
Edge(int from, int to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
}
public class Node {
int value;
int in;
int out;
public List<Node> nexts;
public List<Edge> edges;
}
图的遍历
宽度优先遍历
- 利用队列实现
- 从源节点开始把相邻的点加入队列
- 每弹出一个点,就把它的没进过队列的邻接点放进队列,一直遍历到队列为空
public void bfs(Node source) {
if(source == null) {
return;
}
Queue<Node> queue = new LinkedList<>();
Set<Node> set = new HashSet<>();
while(!queue.isEmpty()) {
Node node = queue.poll();
System.out.print(node);
for(Node next : node.nexts) {
if(!set.contain(next)) {
queue.add(next);
set.add(next);
}
}
}
}
深度优先遍历
public void dfs(Node source) {
if(source == null) {
return;
}
Stack<Node> stack = new Stack<>();
Set<Node> set = new HashSet<>();
stack.push(source);
set.add(source);
System.out.print(source);
while(!stack.isEmpty()){
Node node = stack.pop();
for(Node next : node.nexts) {
if(!set.contain(next)) {
stack.push(node);
stack.push(next);
set.add(next);
System.out.print(next);
break;
}
}
}
}
拓扑排序算法
把节点按照依赖顺序输出
public List<Node> sort(Graph graph) {
HashMap<Node, Integer> inMap = new HashMap<>();
Queue<Node> zeroInQueue = new LinkedList<>();
for(Node node : graph.nodes.values) {
inMap.put(node, node.in);
if(node.in == 0) {
zeroInQueue.add(node);
}
}
List<Node> result = new ArrayList<>();
while(!zeroInQueue.isEmpty()) {
Node cur = zeroInQueue.poll();
result.add(cur);
for(Node next : node.nexts){
inMap.put(next, inMap.get(next) - 1);
if(inMap.get(next) == 0) {
zeroInQueue.add(next);
}
}
}
return result;
}
最小生成树
图连通同时权值最小
K算法(从边的角度出发)
从最小的边开始,如果不会形成环就把边加入
public Set<Edge> KMST(Graph graph) {
UnionFind unionFind = new UnionFind();
unionFind.makeSets(graph.nodes.values());
PriorityQueue<Edge> queue = new PriorityQueue<>((i,j) -> i.weight - j.weight);
for(Edge edge : graph.edges) {
queue.add(edge);
}
Set<Edge> res = new HashSet<>();
while(!queue.isEmpty()) {
Edge edge = queue.poll();
if(!unionFind.isSameSet(edge.from, edge.to)) {
res.add(edge);
unionFind.union(edge.from, edge.to);
}
}
return res;
}
P算法(从点的角度出发)
要求无向图
public Set<Edge> primMST(Graph graph) {
PriorityQueue<Edge> queue = new PriorityQueue<>((e1, e2) -> e1.weight - e2.weight);
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) {
queue.add(edge);
}
while(!queue.isEmpty()) {
Edge edge = queue.poll();
Node toNode = edge.to;
if(!set.contains(toNode)) {
set.add(toNode);
result.add(edge);
for(Edge nextEdge : toNode.edges) {
queue.add(nextEdge);
}
}
}
}
}
return result;
}
迪杰斯特拉算法
从 A 到其他点最短路径
要求权值不能为负数(严格来说,不能有累加和为负数的环)
public HashMap<Node, Integer> dijkstra(Node head) {
HashMap<Node, Integer> distanceMap = new HashMap<>();
distanceMap.put(head, 0);
HashSet<Node> selectedNodes = new HashSet<>();
Node minNode = getMinDistanceAndUnselectedNode(distanceMao, selectedNodes);
while(minNode != null) {
int distance = distanceMap.get(minNode);
for(Edge edge : minNode.edges) {
Node toNode = edge.to;
if(!disatnceMao.containsKey(toNode)) {
distanceMap.put(toNode, distance + edge.weight);
}
distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
}
selectedNodes.add(minNode);
minNode = getMinDistanceAndUnselectedNode(distanceMao, selectedNodes);
}
return distanceMap;
}