//有向图的拓扑排序
//杨鑫
#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. PHP算法之四大基础算法

    前言 虽然工作中,你觉得自己并没有涉及到算法这方面的东西,但是算法是程序的核心,一个程序的好与差,关键是这个程序算法的优劣,所以对于冒泡排序.插入排序.选择排序.快速排序这四种基本算法,我想还是要掌握 ...

  2. 简述Vue的响应式原理

    当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化.每个组 ...

  3. QT5 OpenGL (六, 键盘事件, 开关灯,放大缩小综合运用)

    概要 实例效果图 立体图放大图 立体图缩小图 不加矢量开灯图 不加矢量关灯图 加矢量关灯图1 加矢量关灯图2 部分代码展示 主要内容解析 QT键盘事件 立体图形的放大和缩小 上下左右键以及A键D争键控 ...

  4. objective-c訪问控制符

    objective-c中成员变量的四个訪问控制符: @private:仅仅有当前类的内部才干訪问 @public:全部人都可訪问 @protected:仅仅限当前类和它的子类可以訪问 @package ...

  5. poj3101--Astronomy(分数的最小公倍数)

    题目链接:id=3101">点击打开链接 题目大意:有n个行星,给出每个行星的旋转的周期.问最少多少时间后n个行星会在一条直线上,初始点在一起,不存在全部的行星都有同一个周期 如果A行 ...

  6. 改动android 系统时间

    命令如 date -s "yyyymmdd.[[[hh]mm]ss]" 直接在CRT上执行,举例:date -s "20120801.120503" 但在adb ...

  7. 【LeetCode-面试算法经典-Java实现】【168-Excel Sheet Column Title(Excell列标题)】

    [168-Excel Sheet Column Title(Excell列标题)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a positive in ...

  8. python写个简单的文件上传是有多难,要么那么复杂,要么各种,,,老子来写个简单的

    def upload(url,params): ''' 上传文件到server,不适合大文件 @params url 你懂的 @params {"action":"xxx ...

  9. 朝花夕拾——finally/final/finalize拨云雾见青天

    Java编程中.常常会使用到异常处理,而finally看似的是try/catch后对逻辑处理的完好,事实上里面却存在非常多隐晦的陷阱.final常见于变量修饰,那么你在内部类中也见过吧.finaliz ...

  10. chrome的F12的inspect使用

    chrome中查看cookie https://stackoverflow.com/questions/10014996/how-do-you-check-cookies-using-chrome T ...