数据结构图(Graph)是一种非线性的数据结构,用于表示节点之间的关系。它由节点(Vertex)和边(Edge)组成,每个节点可以与其他节点通过边连接起来。图分为有向图和无向图,顾名思义在有向图中边是有方向的,而在无向图中边是没有方向的。图也可以分为有权图和无权图,有权图是指边具有一个相关联的权重值,无权图是指边没有权重值。
无向有权图的简单实现
import java.util.*;
class WeightedGraph {
private Map> adjacencyList;
public WeightedGraph() {
this.adjacencyList = new HashMap<>();
}
//添加节点
public void addVertex(String vertex) {
adjacencyList.put(vertex, new ArrayList<>());
}
//添加边
public void addEdge(String source, String destination, int weight) {
Edge edge = new Edge(source, destination, weight);
adjacencyList.get(source).add(edge);
// For undirected graph
Edge reverseEdge = new Edge(destination, source, weight);
adjacencyList.get(destination).add(reverseEdge);
}
//删除节点
public void removeVertex(String vertex) {
if (!adjacencyList.containsKey(vertex)) return;
// Remove all edges connected to the vertex
for (String v : adjacencyList.keySet()) {
removeEdge(v, vertex);
}
// Remove the vertex from the graph
adjacencyList.remove(vertex);
}
public void removeEdge(String source, String destination) {
if (!adjacencyList.containsKey(source)) return;
List edges = adjacencyList.get(source);
for (int i = 0; i < edges.size(); i++) {
if (edges.get(i).getDestination().equals(destination)) {
edges.remove(i);
break;
}
}
}
public boolean hasVertex(String vertex) {
return adjacencyList.containsKey(vertex);
}
public boolean hasEdge(String source, String destination) {
if (!adjacencyList.containsKey(source)) return false;
List edges = adjacencyList.get(source);
for (Edge edge : edges) {
if (edge.getDestination().equals(destination)) {
return true;
}
}
return false;
}
public List depthFirstSearch(String startVertex) {
Set visited = new HashSet<>();
List result = new ArrayList<>();
dfsHelper(startVertex, visited, result);
return result;
}
private void dfsHelper(String vertex, Set visited, List result) {
visited.add(vertex);
result.add(vertex);
for (Edge edge : adjacencyList.get(vertex)) {
String neighbor = edge.getDestination();
if (!visited.contains(neighbor)) {
dfsHelper(neighbor, visited, result);
}
}
}
public List breadthFirstSearch(String startVertex) {
Set visited = new HashSet<>();
Queue queue = new LinkedList<>();
List result = new ArrayList<>();
queue.offer(startVertex);
visited.add(startVertex);
while (!queue.isEmpty()) {
String vertex = queue.poll();
result.add(vertex);
for (Edge edge : adjacencyList.get(vertex)) {
String neighbor = edge.getDestination();
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
visited.add(neighbor);
}
}
}
return result;
}
public int shortestPath(String source, String destination) {
Map distances = new HashMap<>();
PriorityQueue pq =
new PriorityQueue<>(Comparator.comparingInt(VertexDistancePairing::getDistance));
// Initialize distances to infinity, except for the source vertex
for (String vertex : adjacencyList.keySet()) {
distances.put(vertex, Integer.MAX_VALUE);
}
distances.put(source, 0);
pq.offer(new VertexDistancePairing(source, 0));
while (!pq.isEmpty()) {
VertexDistancePairing pair = pq.poll();
String currentVertex = pair.getVertex();
if (currentVertex.equals(destination)) {
return pair.getDistance();
}
if (distances.get(currentVertex) < pair.getDistance()) {
continue;
}
for (Edge edge : adjacencyList.get(currentVertex)) {
int newDistance = distances.get(currentVertex) + edge.getWeight();
String neighbor = edge.getDestination();
if (newDistance < distances.get(neighbor)) {
distances.put(neighbor, newDistance);
pq.offer(new VertexDistancePairing(neighbor, newDistance));
}
}
}
// If there is no path between source and destination
return -1;
}
public boolean isConnected(String startVertex, String endVertex) {
Set visited = new HashSet<>();
dfsHelper(startVertex, visited);
return visited.contains(endVertex);
}
private void dfsHelper(String vertex, Set visited) {
visited.add(vertex);
for (Edge edge : adjacencyList.get(vertex)) {
String neighbor = edge.getDestination();
if (!visited.contains(neighbor)) {
dfsHelper(neighbor, visited);
}
}
}
// Additional operations
public List getEdges(String vertex) {
return adjacencyList.containsKey(vertex) ? adjacencyList.get(vertex) : Collections.emptyList();
}
public Map> getAdjacencyList() {
return this.adjacencyList;
}
public int getWeight(String source,String destination){
if(hasEdge(source, destination)){
for(Edge edge: adjacencyList.get(source)){
if(edge.getDestination().equals(destination)){
return edge.getWeight();
}
}
}
return -1; // If there is no edge between source and destination
}
public int getVertexCount() {
return adjacencyList.size();
}
public int getEdgeCount() {
int count = 0;
for (String vertex : adjacencyList.keySet()) {
count += adjacencyList.get(vertex).size();
}
// Divide by 2 as the graph is undirected and each edge is counted twice
return count / 2;
}
public List getAllVertices() {
return new ArrayList<>(adjacencyList.keySet());
}
}
class Edge {
private String source;
private String destination;
private int weight;
public Edge(String source, String destination, int weight) {
this.source = source;
this.destination = destination;
this.weight = weight;
}
public String getSource() {
return source;
}
public String getDestination() {
return destination;
}
public int getWeight() {
return weight;
}
}
class VertexDistancePairing {
private String vertex;
private int distance;
public VertexDistancePairing(String vertex, int distance) {
this.vertex = vertex;
this.distance = distance;
}
public String getVertex(){
return vertex ;
}
public void setVertex(String v){
this.vertex=v ;
}
public Integer getDistance(){
return distance ;
}
public void setDistance(int d){
this.distance=d ;
}
}
常用操作测试:
public class Main {
public static void main(String[] args) {
// 创建一个无向加权图对象
WeightedGraph graph = new WeightedGraph();
// 添加节点
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");
// 添加边
graph.addEdge("A", "B", 5);
graph.addEdge("B", "C", 3);
graph.addEdge("C", "D", 2);
graph.addEdge("D", "A", 4);
// 深度优先搜索
System.out.println(graph.depthFirstSearch("A"));
// 广度优先搜索
System.out.println(graph.breadthFirstSearch("A"));
// 查找最短路径
int shortestPath = graph.shortestPath("A","D");
if (shortestPath != -1) {
System.out.println(shortestPath);
} else {
System.out.println("节点A,D不相连");
}
boolean isConnected = graph.isConnected("A","D");
if (isConnected) {
System.out.println("节点 A,D相连");
} else {
System.out.println("节点A,D不相连");
}
// 删除节点和边
System.out.println(graph.getAdjacencyList()); // 输出初始图
graph.removeEdge("A","B");
System.out.println(graph.getAdjacencyList()); // 移除边 A-B
graph.removeVertex("C");
System.out.println(graph.getAdjacencyList()); // 移除顶点 C
}
}