拓扑排序

定义:

拓扑排序是对有向无圈图的顶点的一种排序,使得如果存在一条边从Vi到Vj的路径,那么在排序中Vj就出现在Vi的后面。

具体实例:

在我们的大学课程中,常出现这么一种情况,比如在选修算法设计前必须先选修数据结构课程。如果,我们用图论来表示的话,(v, w)表示为课程v必须在课程w选修前选修完。

前提:

要满足可以使用拓扑排序的前提是:图中不含有圈。假设存在这样的两个关系(v,w)和(w,v),那么必定是不满足拓扑排序的定义的。

简单拓扑:

先找到任意一个没有入边的顶点,然后显示该顶点,并将它及其边一起从图中删除,然后,再对剩余的点做同样的处理。

伪代码:
    //拓扑排序
    void topsort() throws CycleFoundException{
        for (int counter = 0; counter < NUM_VERTICES; counter ++){
            //查找到入度为0的点
            Vertex v = findNewVertexIndegreeZero();
            if (v == null)
                throw new CycleFoundException();
            //记录该点的位置
            v.topNum = counter;
            //删除掉与v相连的边
            for each Vertex w adjacent to v
                w.indegree--;
        }
    }
改进的拓扑排序:

首先,对每个顶点计算它的入度,然后,将所有入度为0的顶点放入一个初始为空的队列中。当队列不为空时,删除一个顶点v,并将与v邻接的所有顶点的入度减1.只要一个顶点的入度降为0,就把该顶点放入队列中。

伪代码:
void topsort() throws CycleFoundException{
    //用来记录入度为0的顶点
    Queue<Vertex> q = new Queue<Vertext>();
    int counter = 0;
    //将入度为0的顶点加入到队列中
    for each Vertex v
        if (v.indegree == 0)
            q.enqueue(v);
    
    while( !q.isEmpty()){
        //取出队列中的顶点
        Vertex v = q.dequeue();
        //记入该点位置
        v.topNum = ++counter;
        //将与改点相关的边都删除
        for each Vertex w adjacent to v
            //若删边后,该点入度为0,则加入队列中
            if( --w.indegree == 0)
                q.enqueue(w);
    }
    //若counter不等于顶点数,那么说明图中存在圈
    if (counter != NUM_VERTICES)
        throw new CycleFoundException();
}
应用一:判断图中是否存在圈
 public boolean topSort(int numCounts, int[][] inputs){
        //邻接矩阵
        int[][] matrix = new int[numCounts][numCounts];
        //记录顶点的入度
        int[] indegree = new int[numCounts];

        //初始化
        for (int i = 0; i < inputs.length; i ++){
            int front = inputs[i][0];
            int behind = inputs[i][1];
            //排除出现重复的情况,比如出现两次(1,2),(1,2)
            if (matrix[front][behind] == 0)
                indegree[behind] ++;
            matrix[front][behind] = 1;
        }
        //记录个数,用来判断图是否存在圈
        int count = 0;
        //定义队列
        Queue<Integer> queue = new LinkedList<>();
        //将入度为0的顶点加入到队列中
        for (int i = 0; i < indegree.length; i ++){
            if (indegree[i] == 0)
                queue.offer(i);
        }

        while (!queue.isEmpty()){
            //获取到队列中队头
            int current = queue.poll();
            count ++;
            //进行删边
            for (int i = 0; i < numCounts; i ++){
                if (matrix[current][i] != 0){
                    //若删边后,入度为0,则加入队列中
                    if (--indegree[i] == 0)
                        queue.offer(i);
                }
            }
        }
        return count == numCounts;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容