数据结构与算法——有向图邻接表输出其拓扑排序序列

测试数据
输入:
12 16
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
c1 c4
c1 c2
c1 c3
c1 c12
c4 c5
c2 c3
c3 c5
c3 c7
c5 c7
c3 c8
c9 c12
c9 c10
c10 c12
c9 c11
c11 c6
c6 c8
输出:
c1 c12 c3 c2 c4 c10 c9 c8 c7 c5 c11 c6

 Code:

// @ChenYe 2018/11/20
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <stack>
using namespace std;

#define MAX_VERTEX_NUM 20
typedef char VertexType;    // 顶点数据类型
typedef char InfoArc;   // 弧节点相关信息
typedef enum {DG,DN,UDG,UDN} GraphKind;//图类型{有向图,有向网,无向图,无向网}   (边带权值的图叫网)
typedef struct ArcNode  // 弧节点
{
    int adjvex; // 该弧所指向的顶点在数组中的位置
    int value;  // 弧的权值
    struct ArcNode *nextarcs;   // 指向下一条弧的指针
    InfoArc *info;  // 该弧相关信息的指针
}ArcNode;
typedef struct VNode    // 顶点
{
    VertexType data[3];    // 顶点信息
    ArcNode *firstarc;  // 指向第一条依附于该顶点的弧的指针
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct  // 图结构
{
    AdjList vertices;    // 指向订点链表的指针
    int vexnum, arcnum; // 图的当前顶点和弧数
    GraphKind kind;   // 图的种类标志DG,DN,UDG,UDN
}ALGraph;

int visited[MAX_VERTEX_NUM];    // 访问记录数组
int indegree[MAX_VERTEX_NUM];   // 节点入度记录


void CreatGraph_DN(ALGraph &G)
{// 创建邻接表存储的有相图G,并记录节点的入度
    ArcNode *p,*q;
    int i,j,flag1,flag2,value;  // value 接收输入的权值
    VNode v1,v2;
    G.kind = DN;    // 规定为有向图

    // 输入该有向网的顶点数目和弧的数目
    scanf("%d%d",&G.vexnum,&G.arcnum);getchar();
    // 初始化顶点
    for(i=0;i<G.vexnum;i++)
    {
        scanf("%s ",G.vertices[i].data);
        G.vertices[i].firstarc = NULL;
    }
    // 请初始化顶点之间的关系 G.arcnum 条弧
    for(i=0;i<G.arcnum;i++)
    {
        flag1=flag2=-1; // 标记
        scanf("%s %s",v1.data,v2.data);getchar();
        for(j=0;j<G.vexnum;j++)
        {//以下比较字符串可以使用strcmp
            if(G.vertices[j].data[0] == v1.data[0])
                if(G.vertices[j].data[1] == v1.data[1])
                    if(G.vertices[j].data[2] == v1.data[2])
                        flag1 = j;
            if(G.vertices[j].data[0] == v2.data[0])
                if(G.vertices[j].data[1] == v2.data[1])
                    if(G.vertices[j].data[2] == v2.data[2])
                        flag2 = j;
        }

        if(flag1==-1||flag2==-1)    // 错误输入
        {printf("Input error!\n");exit(-1);}

        else    // 在相关顶点的邻接表头插入新弧节点
        {
            p = (ArcNode *)malloc(sizeof(ArcNode));
            p->nextarcs = NULL;
            p->adjvex = flag2;
            // DN 没有权值 p->value==?
            q = G.vertices[flag1].firstarc;
            indegree[flag2]++;  // 节点入度+1

            if(q == NULL)   // 弧链表为空
                G.vertices[flag1].firstarc = p;
            else    // 弧链表不为空,插入到表中
            {
                // 方法一 插入到表尾
                /*
                while(q->nextarcs!=NULL)
                    q = q->nextarcs;
                q->nextarcs = p;
                */
                //方法二插到表头后面
                p->nextarcs = G.vertices[flag1].firstarc;
                G.vertices[flag1].firstarc = p;
            }
        }
    }
}

int FirstAdjVex(ALGraph &G, int v)
{// 返回表示第v个节点的第一个邻接点的数组下标
    if(G.vertices[v].firstarc==NULL)    // 下个节点不存在
        return -1;
    else    // 下个节点存在
        return G.vertices[v].firstarc->adjvex;
}
int NextAdjVex(ALGraph &G, int v, int w)
{// 返回图G中v的邻接链表中边data值为w的下一个节点的数组下表
    ArcNode *p = G.vertices[v].firstarc;
    while(p->adjvex!=w) // 查找v的弧链表上的w的位置
    {
        p = p->nextarcs;
    }
    if(p->nextarcs!=NULL)    // 下个节点存在
        return p->nextarcs->adjvex;
    else    // 下个节点不存在
        return -1;
}

int TopologicalSort(ALGraph G, int *topo)
{// 有向图G采用邻接表储存,若G无回路生成拓扑序列topo{]返回ok,否则返回-1
    stack<int> S;
    int i,k;
    ArcNode *p;
    for(i=0; i<G.vexnum; i++)
        if(indegree[i]==0)
            S.push(i);

    int m = 0;  // 对输出顶点计数,初始化为0

    while(!S.empty())
    {
       i = S.top(); S.pop();
       topo[m] = i;
       m++;
       p = G.vertices[i].firstarc;  // p指向vi的第一个邻接点
       while(p!=NULL)
       {
           k = p->adjvex;
           --indegree[k];
           if(indegree[k]==0)   S.push(k);
           p = p->nextarcs;
       } // <end while>
    }// <end while>

    if(m<G.vexnum)
        return -1; // 有环存在
    else
        return 1;
}

int main()
{
    ALGraph G;
    int topo[MAX_VERTEX_NUM];       // 拓扑排序
    for(int i=0; i<MAX_VERTEX_NUM; i++)
        indegree[i] = 0;
    // 创建
    CreatGraph_DN(G);

    int flag = TopologicalSort(G,topo);
    //printf("flag  %d\n",flag);

    /*printf("topo\n");
    for(int i=0; i<G.vexnum; i++)
        cout<<topo[i]<<" ";*/
    // 输出    
    for(int i=0; i<G.vexnum; i++)
        cout<<G.vertices[topo[i]].data<<" ";
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41420747/article/details/84319023
今日推荐