【排序算法】排序算法-拓扑排序

相关概念

AOV网

  • 一项大的工程常被分为多个小的子工程
    • 子工程之间可能存在一定的先后顺序,即某些子工程必须在其他的一些子工程完成后才能开始
  • 在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,子工程被称为活动(Activity)
    • 以顶点表示活动、有向边表示活动之间的先后关系,这样的图简称为AOV网
  • 标准的AOV网必须是一个有向无环图(Directed Acyclic Graph, 简称 DAG)

在这里插入图片描述

拓扑排序

在这里插入图片描述

  • 前驱活动: 有向边起点的活动称为终点的前驱活动
    • 只有当一个活动的前驱全部都完成后,这个活动才能进行
  • 后继活动: 有向边终点的活动称为起点的后继活动

在这里插入图片描述

  • 什么是拓扑排序?
    • 将AOV网中所有活动排成一个序列,使得每个活动的前驱活动都排在该活动的前面
    • 比如上图的拓扑排序结果是: A、B、C、D、E、F或者是A、B、D、C、E、F(结果并不一定是唯一的)

实现思路

  • 可以使用卡恩算法(kahn于1962年提出)完成拓扑排序
  • 假设L是存放拓扑排序结果的列表
  1. 把所有入度为0的顶点放入L中,然后把这些顶点从图中去掉
  2. 重复操作1,直到找不到入度为0的顶点
  • 如果此时L中的元素个数和顶点总数相同,说明拓扑排序完成
  • 如果此时L中的元素个数少于顶点总数,说明原图中存在环,无法进行拓扑排序

在这里插入图片描述
在这里插入图片描述

实现过程

在这里插入图片描述

  • 首先维护一张入度表和一个list集合,和一个队列
    入度表
    在这里插入图片描述
    队列(初始化将所有的入度为0的顶点放到队列中)
    在这里插入图片描述

  • 将C出队,放到list中,并且遍历所有以C为为起点的边的终点的集合,将这些点的入度-1,如果这些点中存在-1之后入度为0的点,将其加入到队列中。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 将队列中的顶点E出队,放到list中,并且遍历所有以E为为起点的边的终点的集合,将这些点的入度-1, 此轮-1后,点A的入度为0,入队
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • A点出队,放到list集合中,以A点为起点的边的终点集合的入度-1,此轮之后,B,D两点的入度为0,加入到队列中
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • D点出队,加入list集合中
    在这里插入图片描述
    在这里插入图片描述

  • B点出队,加入到list集合中,更新入度表,点F入队在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  • 点F出队,加入到list集合中
    在这里插入图片描述
    在这里插入图片描述

代码

  • 图的接口类
public interface Graph<V, E> {
   
   

    /**
     * 打印边
     */
    void print();

    /**
     * 边的数量
     * @return
     */
    int edgeSize();

    /**
     * 顶点的数量
     * @return
     */
    int vertexSize();

    /**
     * 添加顶点
     * @param v
     */
    void addVertex(V v);

    /**
     * 添加边(无权值)
     * @param from
     * @param to
     */
    void addEdge(V from, V to);

    /**
     * 添加边(有权值)
     * @param from
     * @param to
     * @param weight
     */
    void addEdge(V from, V to, E weight);

    /**
     * 移除顶点
     * @param v
     */
    void removeVertex(V v);

    /**
     * 移除边
     * @param from
     * @param to
     */
    void removeEdge(V from, V to);

    /**
     * 拓扑排序
     * @return
     */
    List<V> topologicalSort();

}

  • 图的实现类
public class ListGraph<V, E> implements Graph<V, E> {
   
   

    private Map<V, Vertex<V, E>> vertices = new HashMap<>();
    private Set<Edge<V, E>> edges = new HashSet<>();

    /**
     * 打印
     */
    @Override
    public void print() {
   
   
        //打印顶点
        vertices.forEach((v, vertex) -> {
   
   
            System.out.println(v);
            System.out.println("out-----------");
            System.out.println(vertex.outEdges);
            System.out.println("in------------");
            System.out.println(vertex.inEdges);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值