/*
Name: 
Copyright: 
Author: 
Date: 17-11-14 21:02
Description: 拓扑排序之变量序列 
如果有n个变量(1<=n<=26,变量名用单个小写字母表示)。还有m个二元组(u,v),分别表示变量u小于v。

那么,全部变量从小到大排列起来应该是什么样子的呢?
比如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b。

虽然还有可能其它的可能,你仅仅需找出当中的一个就可以。
Input
输入为一个字符串data,当中包括N+N个字符。表示N个关系式(1<=N<=100000),比如序列"abcbdc"表示a<b,c<b,d<c.
Output
给出一个字符串,当中存储了一个符合要求的变量序列,比如,字符串"adcb"表示a<d<c<b。

*/
#include<stdio.h>
#include<stdlib.h>

#define true 1  
#define false 0
#define MAXM 26   //最大变量(顶点)数量 
#define MAXN 100000   //最大关系式数量

typedef char VertexType; //顶点类型由用户自己定义
typedef int EdgeType; //边上的权值类型由用户自己定义

typedef struct EdgeNode{ //边表结点
int adjvex;  //邻接点域,存储该顶点相应的下标
// EdgeType weight; //权值。对于非网图能够不须要 
struct EdgeNode *next; //链域,指向下一个邻接点 
} EdgeNode;

typedef struct VertexNode{ //顶点表结点
VertexType data; //顶点域,存储顶点信息
int in;   //存储顶点入度的数量 
EdgeNode *firstEdge; //边表头指针
} VertexNode;

typedef struct Edge{ //边集数组 
int u, v; //弧尾和弧头 
int next; //指向同一个弧尾的下一条边 
// EdgeType weight; //权值,对于非网图能够不须要 
} EdgeLib;

int book[MAXM] = {0}; //标记某字母是否出现

int IsTopoSeq(char *data, char *topo);//依据关系列表data,推断topo字符串是否为拓扑序列 
int CreateGraph(char *data, VertexNode *GL);//创建一个图
void PrintGraph(VertexNode *GL);//输出图
int TopoLogicalSort_DFS(char *topo, VertexNode *GL, int n);//拓扑排序,获取拓扑序列,若存在环则返回假 
int TopoLogicalSort_BFS(char *topo, VertexNode *GL, int n);//拓扑排序,获取拓扑序列。若存在环则返回假 
int CreateGraph_2(char *data, int In[], int first[], EdgeLib edge[]);//创建一个图
void PrintGraph_2(int first[], EdgeLib edge[]);//输出图
int TopoLogicalSort(char *topo, EdgeLib edge[], int In[], int first[], int n);//拓扑排序。获取拓扑序列,若存在环则返回假,使用队列存储拓扑序列

int main()
{
int i, n;
VertexNode GL[MAXM];
char topo[MAXM+1];
char data[MAXN+MAXN+1];
int In[MAXM], first[MAXM]; //存储顶点信息
EdgeLib edge[MAXN]; //存储边信息

gets(data); 
n = CreateGraph_2(data, In, first, edge);//创建一个图
PrintGraph_2(first, edge);//输出图

if (TopoLogicalSort(topo, edge, In, first, n))//採用拓扑排序构造拓扑序列 
puts(topo);
else
puts("不存在满足条件的序列");

if (IsTopoSeq(data, topo))//依据关系列表data。推断topo字符串是否为拓扑序列 
puts(topo);
else
puts("不存在满足条件的序列");

gets(data); 
n = CreateGraph(data, GL);//创建一个图
PrintGraph(GL);//输出图
if (IsTopoSeq(data, topo))//依据关系列表data,推断topo字符串是否为拓扑序列 
puts(topo);
else
puts("不存在满足条件的序列");

if (TopoLogicalSort_BFS(topo, GL, n))//採用拓扑排序构造拓扑序列 
puts(topo);
else
puts("不存在满足条件的序列");

gets(data); 
n = CreateGraph(data, GL);//创建一个图
PrintGraph(GL);//输出图

if (TopoLogicalSort_DFS(topo, GL, n))//採用拓扑排序构造拓扑序列 
puts(topo);
else
puts("不存在满足条件的序列");

if (IsTopoSeq(data, topo))//依据关系列表data,推断topo字符串是否为拓扑序列 
puts(topo);
else
puts("不存在满足条件的序列");

return 0;
}
/*
函数名称:CreateGraph
函数功能:把顶点和边信息读入到表示图的邻接表中 
输入变量:char *data:存储了N个关系式的字符串 
          VertexNode *GL : 顶点表数组 
输出变量:表示图的顶点表数组 
返回值:int :顶点数量 
*/ 
int CreateGraph(char *data, VertexNode *GL)
{
int i, u, v;
int count = 0;//记录顶点数量 
EdgeNode *e;

for (i=0; i<MAXM; i++)//初始化图 
{
GL[i].data = i + 'a';
GL[i].in = 0;
GL[i].firstEdge = NULL;
book[i] = 0;
}

for (i=0; data[i]!='\0'; i+=2)//每次读取两个变量  
{
u = data[i] - 'a'; //字母转换为数字,'a'相应0,'b'相应1。以此类推 
v = data[i+1] - 'a';
book[u] = book[v] = 1;

e = (EdgeNode*)malloc(sizeof(EdgeNode)); //採用头插法插入边表结点 
if (!e)
{
puts("Error"); 
exit(1);
}
e->adjvex = v;
e->next = GL[u].firstEdge;
GL[u].firstEdge = e;

GL[v].in++;
}

for (i=0; i<MAXM; i++)//计算顶点数量 
{
if (book[i] != 0)
count++;
}

return count;
}

void PrintGraph(VertexNode *GL)//输出图
{
int u, v;
EdgeNode *e;

for (u=0; u<MAXM; u++)
{
printf("G[%d] = %c: ", u, GL[u].data);
for (e=GL[u].firstEdge; e!=NULL; e=e->next)//将u的邻接点入度减1。并将入度为0的顶点入栈 
{
v = e->adjvex;
printf("<%c, %c>, ", GL[u].data, GL[v].data);
}
printf("\n");
}
printf("\n");
}

/*
函数名称:TopoLogicalSort_DFS
函数功能:拓扑排序,採用深度优先搜索获取拓扑序列
输入变量:char *topo:用来存储拓扑序列的字符串 
          VertexNode *GL : 顶点表数组 
          int n:顶点个数 
输出变量:用来存储拓扑序列的字符串
返回值:int :拓扑排序成功返回真,若存在环则返回假
*/ 
int TopoLogicalSort_DFS(char *topo, VertexNode *GL, int n)
{
int i, u, v, top;
int count = 0; //用于统计输出顶点的个数 
EdgeNode *e;
int Stack[MAXM];

for (top=i=0; i<MAXM; i++)//将入度为0的顶点入栈 
{
if (book[i] != 0 && GL[i].in == 0)
{
Stack[top++] = i;
}
}

while (top > 0)//採用深度优先搜索获取拓扑序列 
{
u = Stack[--top];
topo[count++] = u + 'a';

for (e=GL[u].firstEdge; e!=NULL; e=e->next)//将u的邻接点入度减1,并将入度为0的顶点入栈 
{
v = e->adjvex;
if (--GL[v].in == 0)
Stack[top++] = v;
}
}
topo[count] = '\0';

return (count == n);//假设count小于顶点数,说明存在环 
}

/*
函数名称:TopoLogicalSort_BFS
函数功能:拓扑排序,採用广度优先搜索获取拓扑序列
输入变量:char *topo:用来存储拓扑序列的字符串 
          VertexNode *GL : 顶点表数组 
          int n:顶点个数 
输出变量:用来存储拓扑序列的字符串
返回值:int :拓扑排序成功返回真。若存在环则返回假
*/ 
int TopoLogicalSort_BFS(char *topo, VertexNode *GL, int n)
{
int i, u, v, front, rear;
EdgeNode *e;

front = rear = 0;
for (i=0; i<MAXM; i++)//将入度为0的顶点入栈 
{
if (book[i] != 0 && GL[i].in == 0)
{
topo[rear++] = i + 'a';
}
}

while (front < rear)//採用广度优先搜索获取拓扑序列 
{
u = topo[front++] - 'a';

for (e=GL[u].firstEdge; e!=NULL; e=e->next)//将u的邻接点入度减1。并将入度为0的顶点入栈 
{
v = e->adjvex;
if (--GL[v].in == 0)
topo[rear++] = v + 'a';
}
}
topo[rear] = '\0';

return (rear == n);//假设count小于顶点数,说明存在环 
}

/*
函数名称:CreateGraph_2
函数功能:把顶点和边信息读入到表示图的边表集中 
输入变量:char *data:存储了N个关系式的字符串 
          int In[]:存储了顶点的入度信息 
          int first[]:指向以该顶点为弧尾的第一条边 
          EdgeLib edge[]:存储了边信息的边表集 
输出变量:表示图的边表集数组 
返回值:int :顶点数量 
*/ 
int CreateGraph_2(char *data, int In[], int first[], EdgeLib edge[])//创建一个图
{
int i, j;
int count = 0;//记录顶点数量

for (i=0; i<MAXM; i++)//初始化图 
{
first[i] = -1;
book[i] = 0;
In[i] = 0;
}

for (j=i=0; data[i]!='\0'; i+=2,j++)//每次读取两个变量  
{
edge[j].u = data[i] - 'a'; //字母转换为数字,'a'相应0,'b'相应1,以此类推 
edge[j].v = data[i+1] - 'a';
book[edge[j].u] = book[edge[j].v] = 1;

edge[j].next = first[edge[j].u];
first[edge[j].u] = j;
In[edge[j].v]++;
}

for (i=0; i<MAXM; i++)//计算顶点数量 
{
if (book[i] != 0)
count++;
}

return count;
}

void PrintGraph_2(int first[], EdgeLib edge[])//输出图
{
int i, j;

for (i=0; i<MAXM; i++)
{
printf("G[%d] = %c: ", i, i+'a');
j = first[i]; //指向i的第一条边 
while (j != -1)
{
printf("<%c, %c>, ", edge[j].u+'a', edge[j].v+'a');
j = edge[j].next; //指向下一条边 
}
printf("\n");
}
printf("\n");

/*
函数名称:TopoLogicalSort
函数功能:拓扑排序。採用广度优先搜索获取拓扑序列
输入变量:char *topo:用来存储拓扑序列的字符串 
          EdgeLib edge[]:存储了边信息的边表集 
          int In[]:存储了顶点的入度信息 
          int first[]:指向以该顶点为弧尾的第一条边 
          int n:顶点个数 
输出变量:用来存储拓扑序列的字符串
返回值:int :拓扑排序成功返回真。若存在环则返回假
*/ 
int TopoLogicalSort(char *topo, EdgeLib edge[], int In[], int first[], int n)
{
int i, u, front, rear;

front = rear = 0;
for (i=0; i<MAXM; i++)//将入度为0的顶点入栈 
{
if (book[i] != 0 && In[i] == 0)
{
topo[rear++] = i + 'a';
}
}

while (front < rear)//採用广度优先搜索获取拓扑序列 
{
u = topo[front++] - 'a';
for (i=first[u]; i!=-1; i=edge[i].next)
{
if (--In[edge[i].v] == 0)
topo[rear++] = edge[i].v + 'a';
}
}
topo[rear] = '\0';

return (rear == n);//假设count小于顶点数。说明存在环 
}

int IsTopoSeq(char *data, char *topo)//依据关系列表data。推断topo字符串是否为拓扑序列 
{
int pos[MAXM] = {0};
int i;

for (i=0; topo[i]!='\0'; i++)//读取变量下标
pos[topo[i]-'a'] = i;

for (i=0; data[i]!='\0'; i+=2)//每次读取两个变量  
{
if (pos[data[i]-'a'] > pos[data[i+1]-'a'])
return false;
}

return true;
}

转载于:https://www.cnblogs.com/liguangsunls/p/7257150.html

拓扑排序之变量序列代码相关推荐

  1. 拓扑排序:如何确定代码源文件的编译依赖关系

    什么是拓扑排序? 由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序 拓扑排序有何应用? 我们知道,一个完整的项目往往会包含很多代码源文件.编译器在编译整个项目的时候,需要按照依赖关 ...

  2. 拓扑排序(完整案列及C语言完整代码实现)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  3. 有向无环图DAG 拓扑排序 代码解释

    目录: DAG定义 举例描述 实际运用 算法描述 算法实战 算法可视化 定义 在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological ...

  4. 图论算法—图的拓扑排序介绍和Kahn算法原理解析以及Java代码的实现

    详细介绍了图的拓扑排序的概念,然后介绍了求拓扑序列的算法:Kahn算法的原理,最后提供了基于邻接矩阵和邻接表的图对该算法的Java实现. 阅读本文需要一定的图的基础,如果对于图不是太明白的可以看看这篇 ...

  5. 对给定的AOV网络,产生所有的拓扑排序结果,并进行解法的动态演示

    数据结构 课程实验报告 实验题目: 33题,对给定的AOV网络,产生所有的拓扑排序结果,并进行解法的动态演示. 实验学时:一周 实验日期: 实验目的:对给定AOV网络,产生所有的拓扑排序结果,并进行动 ...

  6. 图 相关算法~从头学算法【广搜、 深搜、 拓扑排序、 并查集、 弗洛伊德算法、迪杰斯特拉算法】

    图的相关主流算法主要有: 广度优先搜索 深度优先搜索 拓扑排序 并查集 多源最短路径(弗洛伊德算法) 单源最短路径(迪杰斯特拉算法) 其中呢,最基本的是前两种,也就是平时常用的广搜和深搜,本文中将概要 ...

  7. 【图论】有向无环图的拓扑排序

    1. 引言 有向无环图(Directed Acyclic Graph, DAG)是有向图的一种,字面意思的理解就是图中没有环.常常被用来表示事件之间的驱动依赖关系,管理任务之间的调度.拓扑排序是对DA ...

  8. 0x21.搜索 - 树与图的遍历、拓扑排序

    目录 一.树与图的深度优先遍历及树的一些性质 1.树与图的深度优先遍历 2.时间戳 3.树的DFS序(树链剖分前驱知识) 4.树的深度 5.树的重心与sizesizesize 6.图的连通块划分 二. ...

  9. 排个课表学会了拓扑排序!有点意思

    原创不易,帅哥美女呢请三连支持一波 前言 大家好,我是bigsai. 拓扑排序,很多人都可能听说但是不了解的一种算法.不知者大多会提出这样的疑问: 这是某种排序算法?这好像是一种图论算法?图也能排序? ...

最新文章

  1. 套上这个壳,手机自己“跑步”去充电
  2. NSIS:超级轻量皮肤SkinH
  3. python大神写的代码_初学Python,只会写简单的代码。手头有份Python代码,但是调用C模块生成的.pxd和.pyx文件,运行过程总报错,希望大神指点,调试前该做哪些工作呢?...
  4. linux g++ 关闭 ‘typedef’ 警告_Linux学习13CentOS安装mysql5.6环境
  5. java ee7帮助文档_帮助推动Java EE向前发展
  6. 1.Hello,Python
  7. mysql 函数返回查询结果_MySQL数据库中常用查询函数简介
  8. 计算机语言中字体的设置,font-style字体设置详解
  9. html %3ca id=%3e,xss编码小结
  10. android系统性能优化(61)---如何降低Android应用程序的耗电量
  11. bzoj 4006 管道连接 —— 斯坦纳树+状压DP
  12. Codeforces Round #360 (Div. 2) C. NP-Hard Problem 水题
  13. android打开视频噔_如何运行两种游戏数据包(视频教程)
  14. 与其临渊羡鱼,不如退而结网
  15. 对信号与系统课程中Python语言的作业
  16. SolidWorks2022 安装教程
  17. excel宏破解方法
  18. canoco5主成分分析步骤_主成分分析(PCA)统计与MATLAB函数实现
  19. edge浏览器打开html文件路径被拆分,Edge浏览器显示网页排版错位
  20. C/C++播放音乐的函数的学习

热门文章

  1. DBA(五):数据分片、Mycat服务
  2. cron计划任务书写格式
  3. linux中更改文件所有者
  4. Lombok 天天用,却不知道它的原理是什么?
  5. 很遗憾,没有一篇文章能讲清楚ZooKeeper
  6. 又一次生产 CPU 高负载排查实践
  7. 两道JVM面试题,竟让我回忆起了中学时代!
  8. 20万用户同时访问一个热点Key,如何优化缓存架构?
  9. Java 11 已发布,String 还能这样玩!
  10. 如何快速上手一款开源软件