zoukankan      html  css  js  c++  java
  • 图的拓扑排序算法

    什么是图的拓扑排序?

    在实际应用中,有向图的边可以看做是顶点之间制约关系的描述。把顶点看作是一个个任务,则对于有向边<Vi,Vj>表明任务Vj的启动需等到任务Vi完成之后,也就是说任务Vi先于任务Vj完成。

    对于一个有向图,找出一个顶点序列,且序列满足:若顶点Vi和Vj之间有一条边<Vi,Vj>,则在此序列中顶点Vi必在顶点Vj之前。这样的一个序列就称为有向图的拓扑序列(topological order)。

    总之就是:如果G=(V, E)是一个无环的有向图,则G上的拓扑排序指的是图中顶点满足下列条件的一种排序。 若 <v, w> ∈E,则在顶点v必须位于顶点w之前。

    为了方便起见,下面将针对邻接矩阵存储。

    对于拓扑排序算法,采用如下的算法实现:

    1. 从有向图中选取一个没有前驱(入度为0)的顶点输出。
    2. 删除图中所有以它为起点的弧。
    重复上述两个步骤,此时会出现两种情形
    1.所有顶点都已输出,输出序列就是拓扑序列。
    2.已没有无前驱的顶点,但任然有顶点没有输出,这表明该有向图是有环的。
    可见拓扑排序可以检测有向图是否有环。
     
    算法说明:
    使用一个int型的数组indegree,来表示每个顶点的入度。于是,通过查找数组indegree就可得到前驱为零的顶点。下面的代码采取另一种做法:使用一队列,入度为零的顶点入队。这样每次输出入度为零的顶点时,只需出队即可,不必每次都检测整个indegree数组。
     
    具体实现如下所示:
     
    //采用邻接矩阵的形式来存放结点和边的信息
    template <int max_size>
    class Graph 
    {
        private:
            int count;
            bool adjacent[max_size][max_size]; //邻接矩阵中顶点用数组下标表示
        public:
            int indegree(int); //取得结点入度的函数
            void Graph::topologicalsort(void); //拓扑排序函数
    };
    
    //返回结点的入度的函数
    int Graph::indegree(int vertex)
    {
        int num=0;
        for(int i=0;i<max_size;i++)
            if(adjacent[i][vertex] == 0)
                num++;
        return num;
    }
    
    //拓扑排序算法
    void Graph::topologicalsort()
    {
        int vertex;
        queue<int> q; //用对列来存放已经入度为0的结点
        for(int i=0;i<max_size;i++)
            if(indegree[i] == 0)
                q.push(i);
        bool visited[max_size]; //存放访问过的结点
        for(int i=0;i<max_size;i++)
            visited[i] = false;
        while(!q.empty()) //当队列非空的时候循环
        {
            //每次取出一个队列头部的元素进行访问并且输出
            vertex = q.front();
            q.pop();
            cout<<vertex;
            visited[vertex] = true;
            //遍历找到与此结点相邻的断开从此结点出发的弧之后的入度为0的结点,并且压入队列里面
            for(int i=0;i<max_size;i++)
                if(adjacent[vertex][i] == 1)
                {
                    if((--indegree[i]) == 0)
                        q.push(i);
                }
        }
        
        //检测入度为0的点都放入queue里面后还有没有结点没有访问到
        for(int i=0;i<max_size;i++) 
            if(visited[i] == false)
                cout<<"这是个有环的有向图..."<<endl;
        delete []visited; 
    
    }

    参考来源:http://blog.csdn.net/zhangxiangdavaid/article/details/38353517

     
     
     
  • 相关阅读:
    [Tips]git cannot lock ref
    [BUG]Git Sever搭建与相关错误处理
    [Tips]matplotlib 命令行画图保存
    [Tips]Torch功能点记录
    5G元年教育产业再出发 科技赋能的“风口与风险”仍待明晰
    Adobe逆天AI黑科技:美颜照克星,秒还原PS照片
    计算机算法能听声音绘制人脸
    2019 CESA,智能座舱越来越“懂你”
    谷歌首席决策科学家:AI难免犯错,唯有人类可以悬崖勒马
    百度:如何将AI进行到底?
  • 原文地址:https://www.cnblogs.com/jeavenwong/p/8206999.html
Copyright © 2011-2022 走看看