拓扑排序--C语言

来源:互联网 发布:淘宝企业旗舰店 编辑:程序博客网 时间:2024/05/06 12:50

基本思想:
1、在有向图中选一个没有前驱(入度为0)的顶点且输出;
2、从图中删除该顶点和所有以它为尾的边。
重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止(此时说明有向图中存在环)。

#include <stdio.h>#include <stdlib.h>#include <stdbool.h>/*--有向无环图拓扑排序--*/ #define MAX_VERTEX_NUM 20typedef char VertexType;typedef int StackElem;//邻接表存储图 typedef struct ArcNode{    int adjvex;    struct ArcNode *nextarc;}ArcNode;typedef struct VNode{    int indegree;   //图中顶点入度     VertexType data;    ArcNode *firstarc;}VNode,AdjList[MAX_VERTEX_NUM];typedef struct{    AdjList vertices;    int vernum,arcnum;}ALGraph;//创建有向图int locateVex(ALGraph alg,char v){    int i;    for(i=0;i<alg.vernum;i++)    {        if(alg.vertices[i].data == v)        return i;    }    return -1; } void createAOVGraph(ALGraph *alg){    int i,j,k;    char v1,v2;    ArcNode *p,*s;    printf("输入有向图顶点数个和边数:");    scanf("%d %d",&(alg->vernum),&(alg->arcnum));    getchar();    printf("输入顶点名称\n");    for(k=0;k<alg->vernum;k++)    {        printf("输入第%d个顶点名称:",k);        scanf("%c",&(alg->vertices[k].data));        alg->vertices[k].firstarc = NULL;        alg->vertices[k].indegree = 0;        getchar();    }    printf("输入边信息v1 v2\n");    for(k=0;k<alg->arcnum;k++)    {        printf("输入d第%d条边的起止顶点名称:",k);        scanf("%c %c",&v1,&v2);        i = locateVex(*alg,v1);        j = locateVex(*alg,v2);        p = (ArcNode*)malloc(sizeof(ArcNode));        p->adjvex = j;        p->nextarc = NULL;        if(alg->vertices[i].firstarc == NULL)        {            alg->vertices[i].firstarc = p;        }        else        {            s = alg->vertices[i].firstarc;            while(s->nextarc != NULL)                s = s->nextarc;            s->nextarc = p;        }               alg->vertices[j].indegree += 1;   //结点j的入度增加1         getchar();    }  }  //打印有向图 void print(ALGraph G) {    int i;    ArcNode *p;    printf("图的邻接链表(顶点名称 入度:邻接点)\n");     for(i=0;i<G.vernum;i++)    {        printf("%c %d:",G.vertices[i].data,G.vertices[i].indegree);        p = G.vertices[i].firstarc;        while(p!= NULL)        {            printf("%c ",G.vertices[p->adjvex].data);            p = p->nextarc;         }         printf("\n");     }     printf("\n");  } //有向图进行拓扑排序,若有向图没有回路则输出图的一个拓扑排序以OK结尾,否则输出序列以error结束//为避免重复检测入度为0的顶点,设一个栈暂存入度为0的顶点typedef struct SNode{    StackElem index;    struct SNode *snext;}SNode,*PSNode;typedef struct Stack{    PSNode top;    PSNode bottom; }Stack,*PStack;bool stackEmpty(PStack ps){    if(ps->bottom == ps->top)        return true;    return false;}PStack initStack(){    PStack ps = (PStack)malloc(sizeof(Stack));    PSNode p = (PSNode)malloc(sizeof(SNode));    if(p==NULL && ps ==NULL)    {        printf("initstack error!\n");        exit(-1);    }    p->snext = NULL;    ps->bottom = ps->top = p;    return ps; } void push(PStack ps,StackElem index){    PSNode p = (PSNode)malloc(sizeof(SNode));    if(p == NULL)    {        printf("push error!\n");        exit(-1);    }    p->index = index;    p->snext = ps->top;    ps->top = p;}StackElem pop(PStack ps){    if(stackEmpty(ps))    {        printf("stack is NULL\n");        exit(-1);    }    else    {        PSNode p = ps->top;        StackElem index = p->index;        ps->top = p->snext;        free(p);        return index;    }}//拓扑排序 void topologicalSort(ALGraph G){    printf("拓扑排序序列:");     int i,count=0,index;  //count对栈中输出顶点计数     ArcNode *p;    StackElem k;    PStack ps = initStack();    for(i=0;i<G.vernum;i++)    {        if(G.vertices[i].indegree==0)     //入度为0的顶点入栈             push(ps,i);    }    while(!stackEmpty(ps))    {        index = pop(ps);        printf("%c ",G.vertices[index].data);        ++count;        for(p=G.vertices[index].firstarc;p!=NULL;p=p->nextarc)        {            k = p->adjvex;            if((--G.vertices[k].indegree)==0)    //对第index个顶点的每个邻接点的入度减1,若邻接点入度为0,则入栈                 push(ps,k);        }     }     printf("\n");    if(count < G.vernum)        printf("有向图中存在环ERROR!\n");    else        printf("OK!\n"); } int main(){    ALGraph alg;    createAOVGraph(&alg);    print(alg);    topologicalSort(alg);    return 0;}

这里写图片描述

0 0
原创粉丝点击