图论总结-拓扑排序以及最短路径问题(无权最短路径、Dijkstra算法、具有负边值的图)

图的定义

一个图(graph)G = (V,E)顶点(vertex) 集 V 和 边(edge) 集 E 组成。
每一条边就是一个点对(v,w),其中 v,w∈ V,有时也被称为弧(arc)
如果点对是有序的,那么图就叫做是有向的(directed),有向的图有时也叫做有向图(digraph)
顶点 v 和 w 邻接(adjacent) 当且仅当(v,w)∈ E。
有时边还有第三种成分,称作 权(weight)值(cost)
对于一个顶点 v,边(u,v)的条数称为入度(indegree)

图中的一条路径(path) 是一个顶点序列 w1,w2,w3,…wN,使得(wi,wi+1)∈ E,1<= i < N。
这样的一条路径的长(length) 是该条路径上的边数,它等于 N - 1。
一条简单路径是这样的一条路径:其上的所有顶点都是互异的但第一个顶点和最后一个顶点可能相同

有向图中的圈(cycle) 是满足 w1 = wN 且长度至少为 1 的一条路径,如果该条路径是简单路径,那么这个圈就是简单圈
如果一个有向图没有圈,则称其为无圈的(acyclic)。一个有向无圈图有时也简称为 DAG

如果一个无向图中从每一个顶点到每一个其他顶点都存在一条路径,则称该无向图是连通的(connected)
具有这样性质的有向图称为是强连通(strongly connected) 的。
如果边上去掉方向所形成的图是连通的,那么称为基础图(underlying graph)
如果一个有向图不是连通的,但是它是基础图,那么该有向图称为弱连通(weakly connected) 的。
完全图(complete graph) 是其每一对顶点间都存在一条边的图。
稠密图(dense) :图中 E 的条数接近 V*V 也就是,接近任意两点之间相连。
稀疏图(sparse) :图中 E 的条数远小于 V*V。

图的表示

关于图的具体 Java 实现可以点此查看,或点击下面的链接:
https://github.com/0xZhangKe/Algorithms/tree/master/src/com/zhangke/java/graph/adt
我这里是使用邻接表的方式实现的。

邻接矩阵

表示图的一种简单方法是使用一个二维数组,称为邻接矩阵(adjacency matrix)表示法。
适合稠密的图。

邻接表

如果图是稀疏的,则更好的表示方式是使用邻接表(adjacency list)表示。

拓扑排序

拓扑排序是对有向无圈图的顶点的一种排序,他使得如果存在一条从 vi 到 vj 的路径,那么在排序中 vj 出现在 vi 后面。
一个简单的求拓扑排序的算法是先找出任意一个没有入度的顶点。然后我们显示出该顶点,并将它和它的边一起从图中删除。然后,我们对图的其余部分应用同样的方法处理。

public static <T> void sort(ListDGraph<T> graph) {
   
    Queue<Vertex<T>> queue = new ArrayDeque<>();
    Queue<Vertex<T>> resultQueue = new ArrayDeque<>();
    int size = graph.size();
    int[] indegree = new int[size];//入度数组
    for (int i = 0; i < size; i++) {
   
        List<Edge<Vertex<T>>> edges = graph.get(i).getEdgeList();
        for (Edge<Vertex<T>> item : edges) {
   
            indegree[graph.get(item.getDest())]++;
        }
    }
    for (int i = 0; i < size; i++) {
   
        if (indegree[i] == 0) {
   
            queue.offer(graph.get(i));
        }
    }
    while (!queue.isEmpty()) {
   
        Vertex<T> vertex = queue.poll();
        resultQueue.offer(vertex);
        List<Edge<Vertex<T>>> edges = vertex.getEdgeList();
        if (edges != null) {
   
            for (Edge<Vertex<T>> edge : edges) {
   
                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值