图,前缀树,贪心算法
5.0 图
图的存储方式:
-
邻接表(以点为单位,把自己的相邻的点表示出来)
-
邻接矩阵
如何表达图?生成图?有向图?无向图?
描述图
描述点
描述边
如何实现接口函数
5.1 图的宽度优先遍历
跟二叉树的宽度优先遍历有什么区别? 树是没有环的,而图是可能有环的。
图的宽度优先遍历
1,利用队列实现
2,从源节点开始依次按照宽度进队列,然后弹出
3,每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
4,直到队列变空
== 一个点出来后在处理==
5.2 图的深度优先遍历
广度优先遍历
1,利用栈实现
2,从源节点开始把节点按照深度放入栈,然后弹出
3,每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈
4, 直到栈变空
一个点进去时再处理
5.3 拓扑排序算法
适用范围:要求有向图,且有入度为0的节点,且没有环
import包,编译
寻找入度为0的点,然后寻找下一个入度为0 的点。
5.4 prim算法
适用范围:要求无向图
生成最小生成树:一定要保证点的联通性,并且整体边的权值最小
从哪里出发无所谓,所有边都没有被解锁,从第一个点出发,然后进行解锁相邻边,向权重最低的边出发,到达第二个点,在解锁相邻边,依次类推。(如果权重最低的边两个都遍历过了,就找下一个权重最低的边)
package class06;
import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
// undirected graph only
public class Code05_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<>(); // 一次挑选的边在result里
for (Node node : graph.nodes.values()) {
// 处理森林问题,不连通的情况
// 随便挑一个点
// node是开始点
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;
}
5.5 Kruskal算法
1:20:00
适用范围:要求无向图
生成最小生成树:一定要保证点的联通性,并且整体边的权值最小
以边的角度出发,从最小的边出发,加边,然后判断把边加上能不能形成环,形成环的边就不加。(避圈法)
查并集
5.6 Dijkstra算法(迪杰斯特拉)
Dijkstra算法
适用范围:可以有权值为负数的边,不能有累加和为负数的环,单元最短路径算法。
2:04:00
一定要规定出发点,到目标点的最短距离。
先生成:
每一次在这张表中,选距离最短的点,然后该点更新到各点的最短距离,然后该点距离就固定且不用了。然后再挑剩下的距离最短的点,更新该点到各点的最小距离(min(15,3+2))
package class06;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
// no negative weight
public class Code06_Dijkstra {
public static HashMap<Node, Integer> dijkstra1(Node head) {
//从head出发到所有点的最小距离
//key:从head出发到达key
//value:从head出发到达key的最小距离
//如果在表中,没有T的记录,含义是从head出发到T这个点的距离为正无穷
HashMap<Node, Integer> distanceMap = new HashMap<>();
distanceMap.put(head, 0);
//已经求过距离的节点,存在selectedNodes中,以后再也不碰
HashSet<Node> selectedNodes = new HashSet<>();
Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
while (minNode != null) {
int distance = distanceMap.get(minNode);
for (Edge edge : minNode.edges) {
Node toNode = edge.to;
if (!distanceMap.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(distanceMap, selectedNodes);
}
return distanceMap;
}
// 选最小的距离的参数,但是不能是已经选过的点
public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap,
HashSet<Node> touchedNodes) {
Node minNode = null;
int minDistance = Integer.MAX_VALUE;
for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
Node node = entry.getKey();
int distance = entry.getValue();
if (!touchedNodes.contains(node) && distance < minDistance) {
minNode = node;
minDistance = distance;
}
}
return minNode;
}
小根堆方法
系统实现的堆 入堆后 改变不了值。 必须自己手动写
0:12:00
public static class NodeRecord {
public Node node;
public int distance;
public NodeRecord(Node node, int distance) {
this.node = node;
this.distance = distance;
}
}
// 自己改的堆
public static class NodeHeap {
private Node[] nodes; // 所有的节点放在数组里面
private HashMap<Node, Integer> heapIndexMap; // 任何一个节点在数组上的位置是 value值, 进来了弹出去了标为-1
private HashMap<Node, Integer> distanceMap; // 到head的值
private int size; // 一共有多少个节点
public NodeHeap(int size) {
nodes = new Node[size];
heapIndexMap = new HashMap<>();
distanceMap = new HashMap<>();
this.size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public void addOrUpdateOrIgnore(Node node, int distance) {
if (inHeap(node)) {
distanceMap.put(node, Math.min(distanceMap.get(node), distance));
insertHeapify(node, heapIndexMap.get(node)); // 往上交换 交换到小了,只能往上
}
if (!isEntered(node)) {
// 从来没有进来过
nodes[size] = node;
heapIndexMap.put(node, size);
distanceMap.put(node, distance);
insertHeapify(node, size++);
}
// 进来过却不在堆上 ,啥都不做
}
public NodeRecord