网(一.AOV网与拓扑排序)

安允沃
概述:

在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在有向图中若以顶点表示活动,有向边表示活动之间的先后关系,这样的图简称为AOV网。

AOV网

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

简单的说,就是在一个工程中,我们要先做某事,完成后才能做另一件事,比如上图,
我们要先做1和13 ,然后才能做4.
这里的1,13,4就是工程中的活动.
顶点的入度就是活动的先决条件.

我们得到工程的实时路线,就是先做那个活动再做那个活动,直到完工.就得到一组拓扑序列.
如:
13 14 15 5 1 4 8 3 10 11 12 7 9 6 2
是上图的一组拓扑序列
得到这组拓扑序列的算法就是拓扑排序算法

拓扑排序

思路:
1.从AOV网中选择一个没有前趋的顶点(即入度为零),并输出它
2.从网中删除该顶点,并且删除从该顶点发出的全部有向边
3.重复1和2

数据结构:


邻接表

如上图:
我们用邻接表来表示AOV网中的顶点和边
表中每一个元素表示一个活动.
每一个元素有下标,in表示该顶点的入度
data表示顶点的值
first链接的一个链表,表示顶点的出度,链表中的结点有两个属性
first链表中的结点
data:表示改顶点在顶点数组中的下标
next:表示另一个出度顶点

步骤:
首先我们要找出入度为0的顶点,输出
我们将入度为0的顶点全部放入一个栈中.然后依次出栈输出
出栈后要改变顶点所链接的链表中所有元素的入度.

代码:

import org.junit.Test;

public class topologicSort {

    /**
     * 邻接链表结点
     */
    class EdgeNode {
        int data;//存放顶点在顶点数组中的下标
        EdgeNode next;//next结点

        public EdgeNode(int data, EdgeNode next) {
            this.data = data;
            this.next = next;
        }
    }

    /**
     * AOV网中的顶点
     */
    class VertexNode {
        int in;//入度
        int data;//值
        EdgeNode first;//出度领接链表的头结点

        public VertexNode(int in, int data, EdgeNode first) {
            this.in = in;
            this.data = data;
            this.first = first;
        }
    }

    //准备AOV网
    VertexNode[] graphAdjList = new VertexNode[15];

    @Test
    public void test() {
        EdgeNode a = new EdgeNode(3, null);
        EdgeNode a2 = new EdgeNode(2, a);
        EdgeNode a3 = new EdgeNode(1, a2);
        graphAdjList[0] = new VertexNode(0, 1, a3);
        graphAdjList[1] = new VertexNode(2, 2, null);
        EdgeNode b1 = new EdgeNode(9, null);
        EdgeNode b2 = new EdgeNode(8, b1);
        EdgeNode b3 = new EdgeNode(6, b2);
        EdgeNode b4 = new EdgeNode(5, b3);
        graphAdjList[2] = new VertexNode(2, 3, b4);
        EdgeNode c1 = new EdgeNode(7, null);
        EdgeNode c2 = new EdgeNode(9, c1);
        EdgeNode c3 = new EdgeNode(6, c2);
        graphAdjList[3] = new VertexNode(2, 4, c3);
        graphAdjList[4] = new VertexNode(1, 5, null);
        graphAdjList[5] = new VertexNode(1, 6, null);
        graphAdjList[6] = new VertexNode(3, 7, null);
        graphAdjList[7] = new VertexNode(1, 8, null);
        graphAdjList[8] = new VertexNode(1, 9, null);
        EdgeNode d1 = new EdgeNode(10, null);
        EdgeNode d2 = new EdgeNode(6, d1);
        graphAdjList[9] = new VertexNode(2, 10, d2);
        EdgeNode e1 = new EdgeNode(11, null);
        graphAdjList[10] = new VertexNode(1, 11, e1);
        graphAdjList[11] = new VertexNode(1, 12, null);
        EdgeNode f1 = new EdgeNode(3, null);
        EdgeNode f2 = new EdgeNode(13, f1);
        graphAdjList[12] = new VertexNode(0, 13, f2);
        EdgeNode g1 = new EdgeNode(14, null);
        EdgeNode g2 = new EdgeNode(1, g1);
        EdgeNode g3 = new EdgeNode(2, g2);
        graphAdjList[13] = new VertexNode(1, 14, g3);
        EdgeNode h1 = new EdgeNode(4, null);
        graphAdjList[14] = new VertexNode(1, 15, h1);
        topologicalSort();
    }

    private void topologicalSort() {

        //初始化栈,用数组表示,存放顶点在graphAdjList中的下标
        int top = 0;//栈的头指针
        int[] stack = new int[15];
        //找出入度为0的顶点,入栈
        for (int i = 0; i < graphAdjList.length; i++) {
            if (graphAdjList[i].in == 0) {
                stack[++top] = i;//先将top上移一位,因为取出顶点时top会下移,避免取出最后一个顶点时top会为-1.
            }
        }

        while (top != 0) {
            //出栈,输出,修改邻接链表中结点的入度
            int getTop = stack[top--];//取出stack中存放的下标,top下移一位
            System.out.print(graphAdjList[getTop].data + " ");//输出
            for (EdgeNode e = graphAdjList[getTop].first; e != null; e = e.next) {
                int k = e.data;//取出领接链表中结点的值,即该顶点在顶点数组graphAdjList中的下标
                graphAdjList[k].in--;//入度--
                if (graphAdjList[k].in == 0) {//入度为0就入栈
                    stack[++top] = k;
                }
            }
        }
    }

}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容