//有向图的拓扑排序
//杨鑫
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 3
#define MAX_VERTEX_NUM 20
typedef int InfoType; //存放网的权值
typedef char VertexType[MAX_NAME]; //字符串类型
typedef enum{DG, DN, AG, AN}GraphKind; //{有向图,有向网,无向图,无向网}
//图的邻接表存储
typedef struct ArcNode
{
int adjvex; //该弧所指向的顶点的位置
struct ArcNode *nextarc; //指向吓一条的指针
InfoType *info; //网的权值指针
}ArcNode; typedef struct VNode
{
VertexType data; //顶点信息
ArcNode *firstarc; //第一个表结点的地址,指向第一条依附该顶点的弧的指针
}VNode, AdjList[MAX_VERTEX_NUM]; //头结点 typedef struct
{
AdjList vertices;
int vexnum, arcnum; //图的当前顶点数和弧数
int kind; //图的种类标志
}ALGraph; //若G中存在顶点u,则返回该顶点在图中的位置。都则返回-1
int LocateVex(ALGraph G, VertexType u)
{
int i;
for(i = 0; i < G.vexnum; ++i)
{
if(strcmp(u, G.vertices[i].data) == 0)
return i;
return -1;
}
} //採用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图)
int CreateGraph(ALGraph *G)
{
int i, j, k;
int w; //权值
VertexType va, vb;
ArcNode *p;
printf("请输入图的类型(有向图:0,有向网:1。无向图:2,无向网:3):");
scanf("%d", &(*G).kind);
printf("请输入图的顶点数和边数:(以空格间隔): \n");
scanf("%d%d", &(*G).vexnum, &(*G).arcnum);
printf("请输入%d个顶点的值(小于%d个字符):\n", (*G).vexnum, MAX_NAME);
for(i = 0; i < (*G).vexnum; ++i) //构造顶点向量
{
scanf("%s", (*G).vertices[i].data);
(*G).vertices[i].firstarc = NULL;
}
if((*G).kind == 1 || (*G).kind == 3) //网
{
printf("请顺序输入每条弧(边)的权值,弧尾和弧头(以空格作为间隔):\n");
}
else //图
{
printf("请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):\n");
}
for(k = 0; k < (*G).arcnum; ++k)
{
if((*G).kind == 1 || (*G).kind == 3)
scanf("%d%s%s", &w, va, vb);
else
scanf("%s%s", va, vb);
i = LocateVex(*G, va); //弧尾
j = LocateVex(*G, vb); //弧头
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
if((*G).kind == 1 || (*G).kind == 3)
{
p->info = (int *)malloc(sizeof(int));
*(p->info) = w;
}
else
{
p->info = NULL;
}
p->nextarc = (*G).vertices[i].firstarc; //插在表头
(*G).vertices[i].firstarc = p;
if((*G).kind >= 2) //无向图或网。产生第二个表结点
{
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = i;
if((*G).kind == 3)
{
p->info = (int*)malloc(sizeof(int));
*(p->info) = w;
}
else
{
p->info = NULL;
}
p->nextarc = (*G).vertices[j].firstarc; //插在表头
(*G).vertices[j].firstarc = p;
}
}
return 1;
} //输出图的邻接表G
void Display(ALGraph G)
{
int i;
ArcNode *p;
switch(G.kind)
{
case DG:
printf("有向图\n");
break;
case DN:
printf("有向网\n");
break;
case AG:
printf("无向图\n");
break;
case AN:
printf("无向网\n");
}
printf("%d 个顶点: \n", G.vexnum);
for(i = 0; i < G.vexnum; ++i)
{
printf("%s ", G.vertices[i].data);
}
printf("\n%d条弧(边):\n", G.arcnum);
for(i = 0; i < G.vexnum; i++)
{
p = G.vertices[i].firstarc;
while(p)
{
if(G.kind <= 1)
{
printf("%s->%s", G.vertices[i].data, G.vertices[p->adjvex].data);
if(G.kind == DN)
printf(":%d ", *(p->info));
}
else
{
if(i < p->adjvex)
{
printf("%s--%s", G.vertices[i].data, G.vertices[p->adjvex].data);
if(G.kind == AN)
printf(":%d ", *(p->info));
}
}
p = p->nextarc; }
printf("\n");
}
} //求顶点的入度
void FindInDegree(ALGraph G, int indegree[])
{
int i;
ArcNode *p;
//赋初值
for(i = 0; i < G.vexnum; i++)
{
indegree[i] = 0;
}
for(i = 0; i < G.vexnum; i++)
{
p = G.vertices[i].firstarc;
while(p)
{
indegree[p->adjvex]++;
p = p->nextarc;
} } } //栈类型
typedef int SElemType;
#define STACK_INIT_SIZE 10 //存储空间初始分配量
#define STACKINCREMENT 2 //存储空间分配增量 //栈的顺序存储结构表示
typedef struct SqStack
{
SElemType *base; //基地址
SElemType *top; //栈顶指针
int stacksize; //当前已经分配的存储空间
}SqStack; //构造一个空栈
int InitStack(SqStack *S)
{
//为栈底分分配一个指定大小的存储空间
(*S).base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!(*S).base)
exit(0);
(*S).top = (*S).base; //栈底与栈顶指针同样
(*S).stacksize = STACK_INIT_SIZE;
return 1;
} //若栈S为空栈(栈底指针和栈顶指针同样), 则返回1。否则返回0
int StackEmpty(SqStack S)
{
if(S.top == S.base)
return 1;
else
return 0;
} //插入元素e为新的栈顶元素
int Push(SqStack *S, SElemType e)
{
if((*S).top - (*S).base >= (*S).stacksize)
{
(*S).base = (SElemType *)realloc((*S).base,((*S).stacksize + STACKINCREMENT)*sizeof(SElemType));
if(!(*S).base)
exit(0);
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
*((*S).top)++= e;
return 1;
} //若栈不为空,则删除S栈顶元素用e返回其值。并返回1。否则返回0
int Pop(SqStack *S, SElemType *e)
{
if((*S).top == (*S).base)
{
return 0;
}
*e = *--(*S).top;
return 1;
} //有向图的G採用邻接表存储结构。若G无回路,则输出G的顶点的一个拓扑结构
int TopologicalSort(ALGraph G)
{
int i, k, count, indegree[MAX_VERTEX_NUM];
SqStack S;
ArcNode *p;
FindInDegree(G, indegree);
InitStack(&S);
for(i = 0; i < G.vexnum; ++i)
{
if(!indegree[i])
Push(&S, i);
count = 0;
//栈不空
while(!StackEmpty(S))
{
Pop(&S, &i);
printf("%s", G.vertices[i].data); //输出i号顶点并计数
++count;
//对i号顶点的每一个邻接点的入度减1
for(p == G.vertices[i].firstarc; p; p = p->nextarc)
{
k = p->adjvex;
if(!(--indegree[k])) //若入度减为0,则入栈
Push(&S, k);
}
}
if(count < G.vexnum)
{
printf("此有向图有回路\n");
return 0;
}
else
{
printf("为一个拓扑序列!!\n");
}
}
} int main()
{
ALGraph f;
printf("请选择有向图\n");
CreateGraph(&f);
Display(f);
TopologicalSort(f);
return 0;
}

结果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

数据结构之---C语言实现拓扑排序AOV图的更多相关文章

  1. 拓扑排序---AOV图

    对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中全部顶点排成一个线性序列, 使得图中随意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出如 ...

  2. ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TSH OJ-旅行商TSP)

    做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -|| 旅行商(T ...

  3. AOV图与拓扑排序&AOE图与关键路径

    AOV网:所有的工程或者某种流程可以分为若干个小的工程或阶段,这些小的工程或阶段就称为活动.若以图中的顶点来表示活动,有向边表示活动之间的优先关系,则这样活动在顶点上的有向图称为AOV网. 拓扑排序算 ...

  4. C++语言实现-拓扑排序

    1.拓扑排序的概念 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则 ...

  5. 数据结构(C语言版)---排序

    1.排序:重排表中元素. 2.根据数据元素是否完全在内存中,将排序算法分为内部排序和外部排序两类. 3.插入排序:将一个待排序记录按关键字大小插入到前面已排好的子序列中,直到全部记录插入完成. 1)直 ...

  6. hdu 2647 Reward(拓扑排序+反图)

    题目链接:https://vjudge.net/contest/218427#problem/C 题目大意: 老板要给很多员工发奖金, 但是部分员工有个虚伪心态, 认为自己的奖金必须比某些人高才心理平 ...

  7. 2018.08.29 NOIP模拟 table(拓扑排序+建图优化)

    [描述] 给出一个表格,N 行 M 列,每个格子有一个整数,有些格子是空的.现在需要你 来做出一些调整,使得每行都是非降序的.这个调整只能是整列的移动. [输入] 第一行两个正整数 N 和 M. 接下 ...

  8. 拓扑排序(一)之 C语言详解

    本章介绍图的拓扑排序.和以往一样,本文会先对拓扑排序的理论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑 ...

  9. 有向无环图的应用—AOV网 和 拓扑排序

    有向无环图:无环的有向图,简称 DAG (Directed Acycline Graph) 图. 一个有向图的生成树是一个有向树,一个非连通有向图的若干强连通分量生成若干有向树,这些有向数形成生成森林 ...

随机推荐

  1. 论文阅读笔记“Attention-based Audio-Visual Fusion for Rubust Automatic Speech recognition”

    关于论文的阅读笔记 论文的题目是“Attention-based Audio-Visual Fusion for Rubust Automatic Speech recognition”,翻译成中文为 ...

  2. 使用iframe标签时如何通过jquery隐藏滚动条

    通过mouseover和mouseout事件来控制iframe的滚动条 代码如下:

  3. BlogEngine.NET架构学习:Extension扩展实现

    之前有个系列文章介绍过BlogEngine.NET,其中也有关于插件的介绍:"BlogEngine.Net架构与源代码分析系列part9:开发扩展(上)--Extension与管理上的实现& ...

  4. iText操作pdf(生成,导入图片等)

    生成pdf有很多种方法,用pdfbox也很方便,今天我要写的是用iText 主要在pom.xml中配置的jar包如下 <dependency> <groupId>com.low ...

  5. 2014年辛星解读css第三节

    第二节我们讲述的差点儿全是CSS的选择器,那么以下这一节我们来讲一下CSS的颜色和文本的一些东西,尽管我对调色不大敏感.可是对于颜色还是比較感兴趣的. *********CSS中的颜色******** ...

  6. Cacti使用安装具体解释

    Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监測图形分析工具.Cacti是通过 snmpget来获取数据.使用 RRDtool绘绘图形,而且你全然能够不须要了解RRD ...

  7. WAP 图片 lazyload

    原理是根据屏幕上的坐标找到需要做 lazyload 的区域 1,先监听 scroll 事件 ,scrolling_lt window.addEventListener('scroll', functi ...

  8. ThinkPHP新建控制器

    ThinkPHP新建控制器 一.效果图 二.步骤 1.新建控制器文件 2.编写控制器文件 3.访问控制器 三.注意事项

  9. kafka 0.11 spark 2.11 streaming例子

    """ Counts words in UTF8 encoded, '\n' delimited text received from the network every ...

  10. BootStrap学习(二)——重写首页之topbar

    1.布局容器 帮助文档:http://v3.bootcss.com/css/#overview-container BootStrap需要为页面内容和栅栏系统包裹一个.container容器.提供的两 ...