//有向图的拓扑排序
//杨鑫
#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. MySQL的读写分离的几种选择

    MySQL的读写分离的几种选择 MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 原址如下: http://heylinux.com/archives/1004. ...

  2. ItChat与图灵机器人的结合

    前景: 我在知乎关注一位大佬 名字叫 LittleCoder 我是在他开发ItChat包时关注的 ItChat已经完成了微信的个人账号的API接口 已经实现了实时获取用户的即时信息并自动化进行回应 后 ...

  3. [剑指offer] 14. 链表中倒数第K个节点+翻转+逆序打印+合并两个排序链表 + 链表相交(第一个公共节点) (链表)

    题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路:  两个指针,起始位置都是从链表头开始,第一个比第二个先走K个节点,当第一个走到链表尾时,第二个指针的位置就是倒数第k个节点.(两指针始终相 ...

  4. How-to-quick-getting-started-for-Frontend

    一转眼已一年多不专注前端方面的开发工作,这一年前端方面的技术又是新天地,偶然接到内部团队邀请我给他们做一个前端的讲座,希望能帮助他们快速.且深刻了解前端这个行业以及行业内的知识,这可真有点让我为难,由 ...

  5. tp框架报错 Namespace declaration statement has to be the very first statement in the script

    Namespace declaration statement has to be the very first statement in the script tp框架报这个错误,错误行数就是nam ...

  6. js中“原生”map

    var map = {}; // Map map = new HashMap(); map[key] = value; // map.put(key, value); var value = map[ ...

  7. HAVING使用子查询

    HAVING使用子查询     //查询各部门平均工资,显示平均工资大于   //公司整体平均工资的记录   select deptno,avg(sal)   from emp   group by ...

  8. cocos2d-x 移植到android中编译的一些问题:fatal error: Box2D/Box2D.h: No such file or directory&quot;

    1.fatal error: Box2D/Box2D.h: No such file or directory" 须要加入box2d库的支持,改动android.mk文件,例如以下: 查看文 ...

  9. IntelliJ IDEA中JAVA连接MYSQL

    1.下载mysql包 2.项目中引入mysql包 3.连接数据库,查询结果 看jdbc数据库连接类 package Facade; import java.sql.*; /** * Created b ...

  10. BZOJ 2588 主席树

    思路: 主席树 做完BZOJ 3123 觉得这是道水啊-- 然后狂RE 狂MLE 要来数据 忘把deep[1]设成1了----------. 啊wocccccccccccccccc //By Siri ...