| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3767 人关注过本帖, 2 人收藏
标题:实现图的拓扑排序
只看楼主 加入收藏
曲奇琪琪
Rank: 1
来 自:地球
等 级:新手上路
帖 子:1
专家分:0
注 册:2012-9-9
结帖率:0
收藏(2)
已结贴  问题点数:20 回复次数:6 
实现图的拓扑排序
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
/*******************************************/
/*           以下为链式队列操作            */
/*******************************************/
/* 定义链式队列类型 */
typedef int ElemType;
typedef struct QNode
{    ElemType  data;
    struct QNode *next;
}    QNode,*QueuePtr;
typedef struct
{    QueuePtr front;
    QueuePtr rear;
}    LinkQueue;

/* 1.初始化链式队列 */
void InitQueue(LinkQueue *Q)
{    Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
    if (!(Q->front)) exit(0);
    Q->front->next=NULL; }

/* 2.判断空队列 */
int QueueEmpty(LinkQueue Q)
{    if(Q.front==Q.rear)
        return 1;
    else
        return 0; }

/* 3.入队列 */
void EnQueue(LinkQueue *Q, ElemType e)
{    QueuePtr p;
    p=(QueuePtr)malloc(sizeof(QNode));
    if (!p) exit(0);
    p->data=e; p->next=NULL;
    Q->rear->next=p;
    Q->rear=p; }

/* 4.出队列 */
void DeQueue(LinkQueue *Q, ElemType *e)
{    QueuePtr p;
    if(Q->front!=Q->rear)
        {    p=Q->front->next;
            *e=p->data;
            Q->front->next=p->next;
            if (Q->rear==p) Q->rear=Q->front;
            free(p); }
}

/****************************************************/
/*    以下为有向图(DAG)邻接表存储结构(ALG)的操作    */
/****************************************************/
#define MAX_VERTEX_NUM 20 //最大顶点个数
typedef char VertexType[20]; //顶点信息(名称)
/* 图的类型定义(邻接表存储结构) */
typedef struct ArcNode //链表结点
{    int vexpos; //该弧所指向的顶点在数组中的位置
    struct ArcNode *next; //指向当前起点的下一条弧的指针
}    ArcNode;
typedef struct VNode //头结点
{    VertexType name; //顶点信息(名称)
    int indegree; //顶点入度
    ArcNode *firstarc; //指向当前顶点的第一条弧的指针
}    VNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{    AdjList vexhead; //邻接表头结点数组
    int vexnum,arcnum; //图的顶点数和弧数
}    ALGraph;

/* 5.顶点在头结点数组中的定位 */
int LocateVex(ALGraph G,VertexType v)
{    int i;
    for(i=0;i<G.vexnum;i++)
        if(strcmp(v,G.vexhead[i].name)==0) break;
    return i; }

/* 6.建立图(邻接表) */
int CreateGraph(ALGraph *G) //成功建立返回1,不成功则返回0
{    int i,j,k; VertexType v1,v2;ArcNode *newarc;
    printf("\n输入有向图顶点数和弧数vexnum,arcnum:"); //输入顶点数和弧数
    scanf("%d,%d",&(*G).vexnum,&(*G).arcnum); //输入并判断顶点数和弧数是否正确
    if((*G).vexnum<0||(*G).arcnum<0||(*G).arcnum>(*G).vexnum*((*G).vexnum-1))
        {    printf("\n顶点数或弧数不正确,有向图建立失败!\n");return 0; }
    printf("\n输入 %d 个顶点:",(*G).vexnum); //输入顶点名称
    for(i=0;i<(*G).vexnum;i++)
        {    scanf("%s",(*G).vexhead[i].name); }
    printf("\n顶点列表:\n共有%d个顶点:   ",(*G).vexnum);//输出顶点名称
    for(i=0;i<(*G).vexnum;i++)
        printf("%s   ",(*G).vexhead[i].name);
    for(i=0;i<(*G).vexnum;i++) //邻接表初始化
        {    (*G).vexhead[i].firstarc=NULL;
            (*G).vexhead[i].indegree=0;}
    printf("\n\n输入 %d 条边:vi vj\n",(*G).arcnum); //输入有向图的边
    for(k=0;k<(*G).arcnum;k++)
        {    scanf("%s%s",v1,v2); //v1是弧的起点(先决条件),v2是弧的终点
            i=LocateVex(*G,v1);j=LocateVex(*G,v2); //定位顶点并判断顶点是否存在
            if(i>=(*G).vexnum)
                {    printf("顶点%s不存在,有向图建立失败!\n",v1);return 0; }                if(j>=(*G).vexnum)
                {    printf("顶点%s不存在,有向图建立失败!\n",v2);return 0; }
            newarc=(ArcNode*)malloc(sizeof(ArcNode)); //前插法建顶点链表
            newarc->vexpos=j;
            if((*G).vexhead[i].firstarc==NULL)
                {    newarc->next=NULL;
                    (*G).vexhead[i].firstarc=newarc; }
            else
                {    newarc->next=(*G).vexhead[i].firstarc->next;
                    (*G).vexhead[i].firstarc->next=newarc; }
            (*G).vexhead[j].indegree++; //对应顶点入度计数加1
        }
    printf("\n有向图建立成功!\n");
    return 1;
}

/* 7.按邻接表方式输出有向图 */
void PrintGraph(ALGraph G)
{    int i;ArcNode *p;
    printf("\n输出有向图:\n");
    for(i=0; i<G.vexnum; i++)
        {    printf("\n顶点:%s   ",G.vexhead[i].name);
            printf("入度:%3d\n",G.vexhead[i].indegree);
            p=G.vexhead[i].firstarc;
            printf("邻接点:");
            while(p!=NULL)
                {    printf("%s   ",G.vexhead[p->vexpos].name);
                    p=p->next; }
            printf("\n");
        }
}

/**********************************/
/*       以下为拓扑排序算法       */
/**********************************/
/* 8.拓扑排序 */
void TopologicalSort(ALGraph G)
{    int i,k,count;ElemType e;ArcNode *p;
    LinkQueue Q; /*定义队列*/
    InitQueue(&Q);
    for(i=0; i<G.vexnum; i++) //入度为0入队列
        if(!G.vexhead[i].indegree) EnQueue(&Q,i);
    count=0; //初始化变量
    printf("\n\n\n其中一个拓扑排序序列为:\n");
    while(!QueueEmpty(Q))
    {    DeQueue(&Q,&e); //输出入度为零的点
        printf("%s   ",G.vexhead[e].name);
        count++; //对输出的顶点计数
        for(p=G.vexhead[e].firstarc;p;p=p->next) //遍历当前点的邻接点
        {    k=p->vexpos; //邻接点位置
            if(!(--G.vexhead[k].indegree)) //每个邻接点入度减1后若为零则入队列
                EnQueue(&Q,k);
        }
    }
    printf("\n");
    if(count<G.vexnum)
        {    printf("\n该有向图有回路,无法完成拓扑排序!\n"); }
}


/*******************************************/
/*               9.主函数                 */
/*******************************************/
void main()
{    ALGraph G;    int menu,menu2;
    while(1){
    printf("\n        **********************************************\n");
    printf("        *    1.建立有向图并输出                   *\n");
    printf("        *    2.建立有向图并求一个拓扑排序序列     *\n");
    printf("        *    3.清屏                               *\n");
    printf("        *    4.退出                               *\n");
    printf("        **********************************************\n");
    printf("            请输入你的选择:");
    scanf("%d",&menu);
    switch(menu){
    case 1:
        if(CreateGraph(&G)){system("PAUSE");PrintGraph(G);}//有向图建成则执操作
        break;
    case 2:
        if(CreateGraph(&G)) //有向图建成则执操作
            {    system("PAUSE");
                PrintGraph(G);system("PAUSE");
                TopologicalSort(G); }
        break;
    case 3:
        system("CLS");
        break;
    case 4:
        return;
            }
    }
}
    我觉得好问题,望那位高手可以改进下
搜索更多相关主题的帖子: include void next 
2012-09-09 22:54
姻脂梦
Rank: 6Rank: 6
等 级:侠之大者
帖 子:264
专家分:424
注 册:2012-7-3
收藏
得分:3 
帮顶
2012-09-10 00:48
netlin
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:24
帖 子:544
专家分:4308
注 册:2012-4-9
收藏
得分:3 
学习了!

做自己喜欢的事!
2012-09-10 20:18
喝水的鱼
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:50
专家分:113
注 册:2012-9-10
收藏
得分:3 
顶你
2012-09-10 20:55
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:3 
好问题。有空学习一下先。
2012-09-10 21:44
遗矢的老人
Rank: 9Rank: 9Rank: 9
来 自:成都
等 级:蜘蛛侠
威 望:7
帖 子:325
专家分:1131
注 册:2012-7-20
收藏
得分:3 
不错
2012-09-10 23:56
吴军旗
Rank: 5Rank: 5
等 级:职业侠客
帖 子:286
专家分:308
注 册:2011-9-14
收藏
得分:3 
收藏下

最惨的不是忘不了悲伤的回忆,而是那些悲伤的回忆却开始记不清。。。
2012-09-10 23:59
快速回复:实现图的拓扑排序
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.040278 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved