本文参考了 黑马程序员的算法,地址: https://www.bilibili.com/video/BV1rv4y1H7o6?p=76&spm_id_from=pageDriver&vd_source=0af94caf33fbb7a6f7ddfcf5e8c205f4
1.图的基本表示
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Edge {
private Vertex linked;
private int weight;
public Edge(Vertex linked) {
this(linked, 1);
}
public Edge(Vertex linked, int weight) {
this.linked = linked;
this.weight = weight;
}
}
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author laihaonan
* @version 1.0
* @description TODO
* @date 2024/1/24 7:36 上午
*/
@Getter
@Setter
public class Vertex {
private String name;
private List<Edge> edges;
private boolean isVisited;
private Vertex pre;
private int inDegree;
private int dist = Integer.MAX_VALUE;
public Vertex(String name) {
this.name = name;
}
}
2.图的dfs遍历
/**
* b e
* a c g
* d f
* @return
*/
public static void dfsStack(Vertex vertex, List<String> res) {
LinkedList<Vertex> stack = new LinkedList();
stack.push(vertex);
while (!stack.isEmpty()) {
Vertex pop = stack.pop();
pop.setVisited(true);
res.add(pop.getName());
if (CollectionUtil.isNotEmpty(pop.getEdges())) {
for (Edge edge : CollectionUtil.reverse(pop.getEdges())) {
if (!edge.getLinked().isVisited()) {
stack.push(edge.getLinked());
}
}
}
}
}
private static void dfs(Vertex vertex, List<String> res) {
vertex.setVisited(true);
res.add(vertex.getName());
if (CollectionUtil.isNotEmpty(vertex.getEdges())) {
for (Edge edge : vertex.getEdges()) {
if (!edge.getLinked().isVisited()) {
dfs(edge.getLinked(), res);
}
}
}
}
private static Vertex initData() {
Vertex a = new Vertex("a");
Vertex b = new Vertex("b");
Vertex c = new Vertex("c");
Vertex d = new Vertex("d");
Vertex e = new Vertex("e");
Vertex f = new Vertex("f");
Vertex g = new Vertex("g");
Edge edgeb = new Edge(b);
Edge edgec = new Edge(c);
Edge edged = new Edge(d);
Edge edgee = new Edge(e);
Edge edgef = new Edge(f);
Edge edgeg = new Edge(g);
List<Edge> list = new ArrayList<>();
list.add(edgeb);
list.add(edgec);
list.add(edged);
a.setEdges(list);
List<Edge> list2 = new ArrayList<>();
list2.add(edgee);
b.setEdges(list2);
List<Edge> list3 = new ArrayList<>();
list3.add(edgeg);
c.setEdges(list3);
List<Edge> list4 = new ArrayList<>();
list4.add(edgef);
d.setEdges(list4);
List<Edge> list5 = new ArrayList<>();
list5.add(edgeg);
f.setEdges(list5);
List<Edge> list6 = new ArrayList<>();
list6.add(edgeg);
e.setEdges(list6);
return a;
}
3.图的广度遍历
public static void bfsQueue(Vertex vertex, List<String> res) {
LinkedList<Vertex> queue = new LinkedList<>();
queue.offer(vertex);
vertex.setVisited(true);
while (!queue.isEmpty()) {
Vertex poll = queue.poll();
res.add(poll.getName());
if (CollectionUtil.isNotEmpty(poll.getEdges())) {
for (Edge edge : poll.getEdges()) {
if (!edge.getLinked().isVisited()) {
queue.offer(edge.getLinked());
edge.getLinked().setVisited(true);
}
}
}
}
}
4.拓扑排序以及是否有环
public static List<Vertex> topoSort(List<Vertex> graph) {
// 1.统计每个节点的度
for (Vertex v : graph) {
if (CollectionUtil.isNotEmpty(v.getEdges())) {
for (Edge edge: v.getEdges()) {
edge.getLinked().setInDegree(edge.getLinked().getInDegree() + 1);
}
}
}
for (Vertex vertex : graph) {
System.out.print(vertex.getName() + ":" + vertex.getInDegree() + ";");
}
System.out.println("");
// 2.将入度=0的顶点加入队列
LinkedList<Vertex> queue = new LinkedList<>();
for (Vertex vertex : graph) {
if (vertex.getInDegree() == 0) {
queue.offer(vertex);
}
}
// 3.队列不断移除顶点,每移除一个顶点,将相关顶点入度-1,若入度=0,则将顶点入队
List<Vertex> vertices = new ArrayList<>();
while(!queue.isEmpty()) {
Vertex poll = queue.poll();
vertices.add(poll);
if (CollectionUtil.isNotEmpty(poll.getEdges())) {
for (Edge edge : poll.getEdges()) {
edge.getLinked().setInDegree(edge.getLinked().getInDegree() - 1);
if (edge.getLinked().getInDegree() == 0) {
queue.offer(edge.getLinked());
}
}
}
}
return vertices;
}
public static boolean isLooop(List<Vertex> graph) {
List<Vertex> topoSortRes = topoSort(graph);
return topoSortRes.size() != graph.size();
}
private static List<Vertex> initData() {
List<Vertex> graph = new ArrayList<>();
Vertex a = new Vertex("a");
Vertex b = new Vertex("b");
Vertex c = new Vertex("c");
Vertex d = new Vertex("d");
Vertex e = new Vertex("e");
Vertex f = new Vertex("f");
Vertex g = new Vertex("g");
graph.add(a);
graph.add(b);
graph.add(c);
graph.add(d);
graph.add(e);
graph.add(f);
graph.add(g);
Edge edgeb = new Edge(b);
Edge edgec = new Edge(c);
Edge edged = new Edge(d);
Edge edgee = new Edge(e);
Edge edgef = new Edge(f);
Edge edgeg = new Edge(g);
List<Edge> list = new ArrayList<>();
list.add(edgeb);
list.add(edgec);
list.add(edged);
a.setEdges(list);
List<Edge> list2 = new ArrayList<>();
list2.add(edgee);
b.setEdges(list2);
List<Edge> list3 = new ArrayList<>();
list3.add(edgeg);
c.setEdges(list3);
List<Edge> list4 = new ArrayList<>();
list4.add(edgef);
d.setEdges(list4);
List<Edge> list5 = new ArrayList<>();
list5.add(edgeg);
f.setEdges(list5);
List<Edge> list6 = new ArrayList<>();
list6.add(edgeg);
e.setEdges(list6);
return graph;
}
public static void main(String[] args) {
List<Vertex> graph = initData();
List<Vertex> topoSortRes = topoSort(graph);
List<String> strList = new ArrayList<>();
for (Vertex vertex : topoSortRes) {
strList.add(vertex.getName());
}
System.out.println(strList);
System.out.println(isLooop(graph));
}
5.Dijkstra
public static void main(String[] args) {
dijkstra();
dijkstraPriorityQueue();
}
public static List<Vertex> init() {
Vertex v1 = new Vertex("v1");
Vertex v2 = new Vertex("v2");
Vertex v3 = new Vertex("v3");
Vertex v4 = new Vertex("v4");
Vertex v5 = new Vertex("v5");
Vertex v6 = new Vertex("v6");
v1.setDist(0);
Edge edge13 = new Edge(v3, 9);
Edge edge12 = new Edge(v2, 7);
Edge edge16 = new Edge(v2, 14);
List<Edge> edges1 = new ArrayList<>();
edges1.add(edge13);
edges1.add(edge12);
edges1.add(edge16);
v1.setEdges(edges1);
Edge edge14 = new Edge(v4, 20);
List<Edge> edges2 = new ArrayList<>();
edges2.add(edge14);
v2.setEdges(edges2);
Edge edge36 = new Edge(v6, 2);
Edge edge34 = new Edge(v4, 11);
List<Edge> edges3 = new ArrayList<>();
edges3.add(edge36);
edges3.add(edge34);
v3.setEdges(edges3);
Edge edge45 = new Edge(v5, 6);
List<Edge> edges4 = new ArrayList<>();
edges4.add(edge45);
v4.setEdges(edges4);
Edge edge65 = new Edge(v5, 9);
List<Edge> edges6 = new ArrayList<>();
edges6.add(edge65);
v6.setEdges(edges6);
List<Vertex> list = new ArrayList<>();
list.add(v1);
list.add(v2);
list.add(v3);
list.add(v4);
list.add(v5);
list.add(v6);
return list;
}
public static void dijkstra() {
List<Vertex> graph = init();
List<Vertex> graph2 = new ArrayList<>(graph);
getDist(graph2);
for (Vertex vertex : graph) {
System.out.println(vertex.getName() + " " + vertex.getDist());
}
}
public static void dijkstraPriorityQueue() {
List<Vertex> graph = init();
PriorityQueue<Vertex> dijkstraPriorityQueue =
new PriorityQueue<>((v1, v2) -> v1.getDist() - v2.getDist());
for (Vertex vertex : graph) {
dijkstraPriorityQueue.add(vertex);
}
while (!dijkstraPriorityQueue.isEmpty()) {
Vertex minDiskVertex = dijkstraPriorityQueue.peek();
updateWeighBoursDist(minDiskVertex, dijkstraPriorityQueue);
dijkstraPriorityQueue.poll();
}
for (Vertex vertex : graph) {
System.out.println(vertex.getName() + " " + vertex.getDist());
}
}
public static void getDist(List<Vertex> notCompleteVisitedList) {
while (!notCompleteVisitedList.isEmpty()) {
Vertex minDistVertex = findMinDistVertex(notCompleteVisitedList);
updateWeighBoursDist(minDistVertex, notCompleteVisitedList);
notCompleteVisitedList.remove(minDistVertex);
}
}
/**
* 更新相邻顶点的距离
* @param cur 从当前顶点出发
* @param list 所有没有访问完成的顶点集合
*/
public static void updateWeighBoursDist(Vertex cur, List<Vertex> list) {
if (CollectionUtil.isNotEmpty(cur.getEdges())) {
for (Edge edge : cur.getEdges()) {
Vertex n = edge.getLinked();
if (list.contains(n)) {
int dist = cur.getDist() + edge.getWeight();
if (dist < n.getDist()) {
n.setDist(dist);
}
}
}
}
}
public static Vertex findMinDistVertex(List<Vertex> graph) {
if (CollectionUtil.isNotEmpty(graph)) {
Vertex min = graph.get(0);
for (int i = 1; i < graph.size(); i++) {
if (min.getDist() > graph.get(i).getDist()) {
min = graph.get(i);
}
}
return min;
}
return null;
}
6.Test
public static void main(String[] args) {
Vertex vertex = initData();
List<String> res = new ArrayList<>();
dfs(vertex, res);
System.out.println(JSON.toJSONString(res));
List<String> res1 = new ArrayList<>();
vertex = initData();
dfsStack(vertex, res1);
System.out.println(JSON.toJSONString(res1));
List<String> res2 = new ArrayList<>();
vertex = initData();
bfsQueue(vertex, res2);
System.out.println(JSON.toJSONString(res2));
/**
* 基础: LinkedList用于stack
*/
List<String> stackRes = new ArrayList<>();
LinkedList<String> list = new LinkedList();
list.push("1");
list.push("2");
list.push("3");
list.push("4");
list.push("5");
for (int i = 0; i < 5; i++) {
stackRes.add(list.pop());
}
System.out.println(JSON.toJSONString(stackRes));
/**
* 基础: LinkedList用于queue
*/
List<String> queueRes = new ArrayList<>();
LinkedList<String> queue = new LinkedList();
queue.push("1");
queue.push("2");
queue.push("3");
queue.push("4");
queue.push("5");
for (int i = 0; i < 5; i++) {
queueRes.add(queue.pollLast());
}
System.out.println(JSON.toJSONString(queueRes));
}