zoukankan      html  css  js  c++  java
  • 拓扑排序

    可以将图的拓扑排序看作是将图的所有结点在同一水平线上排开,图的所有有向边都从左指向右.

    有向无环图的拓扑排序算法:

    Toplogical-Sort(G)
        call DFS(G) to compute finish times v.f for each vertex v
        as each vertex is finished,insert onto the front of a linked list
       //因为后被发现的结点的完成时间小于先被发现的结点 //实际上这里是按完成时间将结点从小到大排序 return the linked list of vertices

    时间复杂度:O(|V|+|E|)

    另一种算法:重复寻找入度为0的结点,输出该结点,将该结点及从其出发的边删除.

    void find_indegree(Graph G,vector<int> &indegree){
        for(int i=0;i<G.Adj.size();++i){
            indegree.push_back(G.Adj[i].indegree);
        }
    }
    void toplogical_sort2(Graph G){
        vector<int> indegree;
        find_indegree(G,indegree);
        stack<int> S;
        for(int i=0;i<G.Adj.size();++i){
            if(!indegree[i]){
                S.push(i);//入度为0的结点入栈
            }
        }
        int count = 0;
        while(!S.empty()){
            int i=S.top();//栈顶元素出栈
            S.pop();
            cout<<G.Adj[i].vertex<<",";
            ++count;
            for(auto p=G.Adj[i].firstNode;p != nullptr;p = p->next){
                int k=p->index;
                            //删除从结点i出发的边
                if(!(--indegree[k])){
                    S.push(k);
                }
            }
        }
        assert(count == G.Adj.size());//若count<G.Adj.size(),则图中有回路
    }

    时间复杂度:O(|V|+|E|)

    编码实现:

    #include<iostream>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #include<stack>
    #include<cassert>
    using namespace std;
    enum Color{white,gray,black};
    
    vector<pair<int,int>> toplogical_list;
    
    class Node{
    public:
        int index;
        Node* next=nullptr;//
        Node(int i):index(i){}
    };
    
    class VNode{
    public:
        char vertex;
        int dist;
        int final;
        int indegree;
        Color color=white;
        int prev=-1;
        Node* firstNode=nullptr;
        VNode(char c):vertex(c){}
    };
    
    
    typedef struct Graph{
        int EdgeNum;
        vector<VNode> Adj;
    }Graph;
    
    void DFS_VISIT(Graph &G,int u);
    int timex;
    void DFS(Graph &G){
        for(int i=0;i<G.Adj.size();i++){
            G.Adj[i].color = white;
            G.Adj[i].prev = -1;
        }
         timex =0;
         //begin from a certain vertex
         //DFS_VISIT(G,inndex);
        for(int i=0;i<G.Adj.size();i++){
            if(G.Adj[i].color == white){
                DFS_VISIT(G,i);
            }
        }
    }
    
    void DFS_VISIT(Graph &G,int u){
        timex += 1;
        G.Adj[u].dist = timex;
        G.Adj[u].color = gray;
        //cout<<G.Adj[u].vertex<<",";
        
        Node* pv = G.Adj[u].firstNode;
        while(pv != nullptr){
            int v= pv->index;
            if(G.Adj[v].color == white){
                G.Adj[v].prev = u;
                DFS_VISIT(G,v);
            }
            pv = pv->next;
        }
        G.Adj[u].color = black;
        timex += 1;
        G.Adj[u].final = timex;
        toplogical_list.push_back(make_pair(u,timex));
    }
    
    int comp(pair<int,int> a,pair<int,int> b){
        if(a.second>b.second){
            return -1;
        }
        else if(a.second==b.second){
            return 0;
        }
        else{
            return 1;
        }
    }
    void toplogical_sort(Graph G){
        DFS(G);
        sort(toplogical_list.begin(),toplogical_list.end(),comp);
        for(const auto &c:toplogical_list ){
            cout<<G.Adj[c.first].vertex<<",";
        }
        cout<<endl;
    }
    
    void find_indegree(Graph G,vector<int> &indegree){
        for(int i=0;i<G.Adj.size();++i){
            indegree.push_back(G.Adj[i].indegree);
        }
    }
    void toplogical_sort2(Graph G){
        vector<int> indegree;
        find_indegree(G,indegree);
        stack<int> S;
        for(int i=0;i<G.Adj.size();++i){
            if(!indegree[i]){
                S.push(i);
            }
        }
        int count = 0;
        while(!S.empty()){
            int i=S.top();
            S.pop();
            cout<<G.Adj[i].vertex<<",";
            ++count;
            for(auto p=G.Adj[i].firstNode;p != nullptr;p = p->next){
                int k=p->index;
                if(!(--indegree[k])){
                    S.push(k);
                }
            }
        }
        assert(count == G.Adj.size());
    }
    
    int main(){
        Graph G;
        G.EdgeNum = 9;
        //vector<char> v{'v','r','s','w','x','y','t','u'};
        vector<char> v{'v','r','s','w','x','y','t','u','p'};
        for(int i=0;i<v.size();i++){
            G.Adj.push_back(VNode(v[i]));
        }
    
        int i,j;
        for(int k=0;k<G.EdgeNum;k++){
            cin>>i>>j;
            Node* p = new Node(j);
            p->next = G.Adj[i].firstNode;
            G.Adj[i].firstNode = p;
    
            ++G.Adj[j].indegree;
            /*
            p = new Node(i);
            p->next = G.Adj[j].firstNode;
            G.Adj[j].firstNode = p;
            */
        }
        //DFS(G);
        toplogical_sort(G);
        toplogical_sort2(G);
        cout<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    Matlab曲面拟合和插值
    插值(scipy.interpolate)
    坐标系旋转后的点坐标、坐标点旋转后的点坐标
    halcon相机标定及图像矫正
    别再问我们用什么画图的了!问就是excalidraw
    Windows下如何玩转火热的go-zero
    我用go-zero开发了第一个线上项目
    Java基础差,需要怎么补
    2019-给你六个建议
    简说Java线程的那几个启动方式
  • 原文地址:https://www.cnblogs.com/bukekangli/p/4395791.html
Copyright © 2011-2022 走看看