天天看點

判斷有向圖是否有回路的另外一種方法--拓撲排序

#include <iostream>

#include <string>

#include <queue>

using namespace std;

typedef struct Edgenode

{

    int adjvex;

    struct Edgenode *next;

}Edgenode;

typedef struct Vertexnode

{

    string data;

    Edgenode *firstedge;

}Vertexnode,Adjlist[10];

typedef struct Graph

{

    Adjlist vertex_node;

    int num_vertex;

    int num_edge;

}Graph;

int get_location(Graph g, string s)

{

    int i;

    for(i=0;i<g.num_vertex;i++)

    {

        if(s == g.vertex_node[i].data)

            return i;

    }

    return -1;

}

void create_graph(Graph &g)//建立有向圖

{

    int i,j,k;

    string s1,s2;

    cout<<"請輸入頂點數和邊數:";

    cin>>g.num_vertex>>g.num_edge;

    cout<<"請輸入頂點:";

    for(i=0;i<g.num_vertex;i++)

    {

        cin>>g.vertex_node[i].data;

        g.vertex_node[i].firstedge = NULL;

    }

    cout<<"請輸入邊:"<<endl;

    for(k=0;k<g.num_edge;k++)

    {

        cin>>s1>>s2;

        i = get_location(g,s1);

        j = get_location(g,s2);

        Edgenode *p = new Edgenode();

        p->adjvex = j;

        p->next = g.vertex_node[i].firstedge;

        g.vertex_node[i].firstedge = p;

    }

}

void print_graph(Graph g)//列印鄰接表

{

    cout<<"鄰接表如下:"<<endl;

    int i;

    for(i=0;i<g.num_vertex;i++)

    {

        cout<<g.vertex_node[i].data;

        Edgenode *p = g.vertex_node[i].firstedge;

        while(p)

        {

            cout<<"->"<<g.vertex_node[p->adjvex].data;

            p = p->next;

        }

        cout<<endl;

    }

}

void find_indegree(Graph g, int indegree[])//計算每個頂點的入度

{

    int i;

    for(i=0;i<g.num_vertex;i++)

        indegree[i]=0;

    for(i=0;i<g.num_vertex;i++)

    {

        Edgenode *p = g.vertex_node[i].firstedge;

        while(p)

        {

            indegree[p->adjvex]++;

            p=p->next;

        }

    }

}

void topologicalsort(Graph g)//拓撲排序

{

    int indegree[10];//入度

    int count = 0;//計數

    find_indegree(g,indegree);

    int i;

    queue<int> q;

    for(i=0;i<g.num_vertex;i++)//把度為0的頂點入隊

    {

        if(indegree[i]==0)

            q.push(i);

    }

    while(!q.empty())

    {

        int k = q.front();

        q.pop();

        cout<<g.vertex_node[k].data<<" ";

        count++;

        Edgenode *p = g.vertex_node[k].firstedge;

        while(p)

        {

            if(--indegree[p->adjvex]==0)//将度為0的頂點的鄰接頂點入度減1,如果變為0則将其入隊

                q.push(p->adjvex);

            p=p->next;

        }

    }

    cout<<endl;

    if(count != g.num_vertex)//如果最終計數值和頂點數不相等,說明有的頂點入度沒有變為0,存在環路

        cout<<"有向圖存在環路!"<<endl;

}

int main()

{

    Graph g;

    create_graph(g);

    print_graph(g);

    cout<<"拓撲排序:"<<endl;

    topologicalsort(g);

    return 0;

}

測試用例一:

判斷有向圖是否有回路的另外一種方法--拓撲排序
判斷有向圖是否有回路的另外一種方法--拓撲排序

測試用例二:

判斷有向圖是否有回路的另外一種方法--拓撲排序
判斷有向圖是否有回路的另外一種方法--拓撲排序

繼續閱讀