作为开发人员,我们经常处理列表,数组和值序列。 但是,您是否曾经不得不处理与其他数据相关的相关数据? 这也称为图形。
These days I had to deal with it. It was scary at first.
But after reading this great article from Kumar Chandrakant, it became understandable and I felt capable of doing that.
当然,还有很多东西要学习,但是我将向您展示基础知识,因此您有一个起点来加深您的研究。
一种 graph is a collection of Vertices (also called Nodes or Points) and Edges (also called Links or Lines), where an edge is the connections between two vertices.
In a social network, each person is a vertex, and each connection between them is the edge.
In a map, the streets are the edges and their intersections are the vertices.
![Route on map](https://i-blog.csdnimg.cn/blog_migrate/6aa945872e9ea05df30879a1bbdb2997.jpeg)
使用库马尔的图作为示例,让我们编写代码。 第一步是创建一个顶点类:
public class Vertex {
String name;
Vertex(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
return ((o instanceof Vertex) && (((Vertex) o).getName() == this.name));
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + name.hashCode();
return result;
}
@Override
public String toString() {
return name;
}
}
基本上,顶点只有“名称”属性。 但是,由于我们将使用Java集合,因此必须重写等于,hashCode,and toString方法。
现在,该图形类:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Graph {
private Map<Vertex, List<Vertex>> adjVertices;
public Graph() {
this.adjVertices = new HashMap<Vertex, List<Vertex>>();
}
void addVertex(String name) {
adjVertices.putIfAbsent(new Vertex(name), new ArrayList<>());
}
void addEdge(String name1, String name2) {
Vertex v1 = new Vertex(name1);
Vertex v2 = new Vertex(name2);
adjVertices.get(v1).add(v2);
adjVertices.get(v2).add(v1);
}
List<Vertex> getAdjVertices(String name) {
return adjVertices.get(new Vertex(name));
}
String printGraph() {
StringBuffer sb = new StringBuffer();
for(Vertex v : adjVertices.keySet()) {
sb.append(v);
sb.append(adjVertices.get(v));
sb.append("\n");
}
return sb.toString();
}
}
我们正在使用地图创建一个邻接表。 该列表将包含每个顶点的所有关系。 添加边时,我们在相关顶点的列表上添加一个顶点。 To represent the graph, we print the 邻接表, creating a string that starts with each vertex and shows the related list in front of it.
然后,我们将创建一个ves类,它将包含遍历图的方法。 两种方法都会收到图形还有一个根(这将是我们的起点)作为参数。 There are several ways for traversing a 图形, but in this article, we will only show the two most commonly used。 They are known as 深度优先遍历(DFT)和广度优先遍历(BFT)。 它们之间的主要区别在于DFT每次拜访儿童连接直到结束,然后再开始访问兄弟姐妹。 的BFT, on the other hand,每次拜访兄弟首先先拜访他们的儿童ren。
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
public class Traversal {
static Set<String> depthFirstTraversal(Graph graph, String root) {
Set<String> visited = new LinkedHashSet<String>();
Stack<String> stack = new Stack<String>();
stack.push(root);
while(!stack.isEmpty()) {
String vertex = stack.pop();
if (!visited.contains(vertex)) {
visited.add(vertex);
for (Vertex v : graph.getAdjVertices(vertex)) {
stack.push(v.name);
}
}
}
return visited;
}
static Set<String> breadthFirstTraversal(Graph graph, String root) {
Set<String> visited = new LinkedHashSet<String>();
Queue<String> queue = new LinkedList<String>();
queue.add(root);
visited.add(root);
while (!queue.isEmpty()) {
String vertex = queue.poll();
for (Vertex v : graph.getAdjVertices(vertex)) {
if (!visited.contains(v.name)) {
visited.add(v.name);
queue.add(v.name);
}
}
}
return visited;
}
}
请注意DFT我们使用堆存储将要遍历的顶点,这使我们在每个顶点都更深入。 在里面BFT,我们使用队列存储顶点,这首先使我们成为邻居。
最后,我们在main方法中创建一个图,定义它的顶点和边,然后打印邻接表并使用两种遍历遍历它。
public class TraverseGraph {
public static void main(String[] args) {
Graph graph = new Graph();
graph.addVertex("Bob");
graph.addVertex("Alice");
graph.addVertex("Mark");
graph.addVertex("Rob");
graph.addVertex("Maria");
graph.addEdge("Bob", "Alice");
graph.addEdge("Bob", "Rob");
graph.addEdge("Alice", "Mark");
graph.addEdge("Rob", "Mark");
graph.addEdge("Alice", "Maria");
graph.addEdge("Rob", "Maria");
System.out.println(graph.printGraph());
System.out.println(Traversal.depthFirstTraversal(graph, "Bob"));
System.out.println(Traversal.breadthFirstTraversal(graph, "Bob"));
}
}
结果将是以下内容:
Bob[Alice, Rob]
Rob[Bob, Mark, Maria]
Mark[Alice, Rob]
Alice[Bob, Mark, Maria]
Maria[Alice, Rob]
[Bob, Rob, Maria, Alice, Mark]
[Bob, Alice, Rob, Mark, Maria]
我希望本文能阐明图表。 Leave your impressions or doubts。
Sources:
[1]https://www.baeldung.com/java-graphs
[2]https://dev.to/amberjones/intro-to-graph-data-structures-abk
[3]https://dev.to/vaidehijoshi/going-broad-in-a-graph-bfs-traversal
[4]https://dev.to/jjb/part-9-learning-graphs-4859