Graph简介

概念

数据结构图(Graph)是一种非线性的数据结构,用于表示节点之间的关系。它由节点(Vertex)和边(Edge)组成,每个节点可以与其他节点通过边连接起来。图分为有向图和无向图,顾名思义在有向图中边是有方向的,而在无向图中边是没有方向的。图也可以分为有权图和无权图,有权图是指边具有一个相关联的权重值,无权图是指边没有权重值。

特点

  • 非线性结构:图中的节点和边形成复杂的连接关系,不同于数组、链表等线性结构。
  • 可变大小:图可以动态增长或缩小,并且支持添加、删除、修改节点和边。
  • 实体关系表示:适合用于表示实体对象之间的相互关系,如社交网络中用户之间的好友关系。

优点

  1. 模型灵活性高:可以模拟各种现实情况下复杂而多样化的问题,并提供了多种算法来解决这些问题。
  2. 具备强大搜索能力:通过遍历算法如深度优先搜索 (DFS) 和广度优先搜索 (BFS),能够有效地查找特定元素或路径。

缺点

  1. 占用更多内存空间:相比线性结构,图可能需要更多的空间来存储节点和边之间的关系。
  2. 高复杂度:某些图算法的时间复杂度相对较高,尤其在大规模数据上进行操作时。

适用场景

  • 社交网络分析。
  • 地图导航系统。
  • 网络拓扑结构表达和分析。

实现代码:

无向有权图的简单实现

import java.util.*;

class WeightedGraph {
    private Map<String, List<Edge>> 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<Edge> 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<Edge> edges = adjacencyList.get(source);

        for (Edge edge : edges) {
            if (edge.getDestination().equals(destination)) {
                return true;
            }
        }

        return false;
    }

    public List<String> depthFirstSearch(String startVertex) {
        Set<String> visited = new HashSet<>();
        List<String> result = new ArrayList<>();

        dfsHelper(startVertex, visited, result);

        return result;
    }

    private void dfsHelper(String vertex, Set<String> visited, List<String> 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<String> breadthFirstSearch(String startVertex) {
        Set<String> visited = new HashSet<>();
        Queue<String> queue = new LinkedList<>();
        List<String> 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<String, Integer> distances = new HashMap<>();
        PriorityQueue<VertexDistancePairing> 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<String> visited = new HashSet<>();

        dfsHelper(startVertex, visited);

        return visited.contains(endVertex);
    }

    private void dfsHelper(String vertex, Set<String> 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<Edge> getEdges(String vertex) {
        return adjacencyList.containsKey(vertex) ? adjacencyList.get(vertex) : Collections.emptyList();
    }

    public Map<String,List<Edge>> 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<String> 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

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大宝贱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值