• 拓补排序简介

    • 实现过程
    • 代码实现

拓补排序简介

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

首先需要知道一个概念:入度。

通常指有向图中某点作为图中边的终点的次数之和。

比如:

节点 A B C D E
入度 0 1 1 1 3

实现过程

对图进行深度优化搜索,将顶点放入数组中,改变与之连接的下个节点的入度。

图片取自:拓扑排序(Topological Sorting)

代码实现

核心代码:

BOOLEAN isInTop(VTYPE *topNum, int length, VTYPE key) {for (int i = 0; i < length; i++) {if (topNum[i] == key) {return TRUE;}}return FALSE;
}int degreePos(AdjGraphPtr adj, VTYPE *topNum , int length) {int pos = -1;for (int i = 0; i < adj->vNum; i++) {if (adj->vertexList[i]->degree == 0) {if (isInTop(topNum, length, adj->vertexList[i]->v) == FALSE) {pos = i;return pos;}}}return pos;
}int getEmptyPos(VTYPE *topNum, int length) {//获得未使用的位置for (int i = 0; i < 5; i++) {if (topNum[i] == 0) {return i;}}return -1;
}int dfs(AdjGraphPtr adj, VTYPE *topNum, int length, int pos) {EdgePtr tmp = adj->vertexList[pos]->firstEdge;while (tmp != NULL) {VTYPE w = tmp->w;int w_pos = getVertexPos(adj, w);adj->vertexList[w_pos]->degree--;if (adj->vertexList[w_pos]->degree == 0)continue;if (isInTop(topNum, length, w) == FALSE) {int emptyPos = getEmptyPos(topNum, length);if(emptyPos != -1)topNum[emptyPos] = w;}dfs(adj, topNum, length, w_pos);tmp = tmp->next;}
}void topSort(AdjGraphPtr adj, int length) {VTYPE topNum[5];for (int i = 0; i < length; i++) {topNum[i] = 0;}for (int i = 0; i < length; i++) {int pos = degreePos(adj, topNum, length);if (pos == -1) {return;}int emptyPos = getEmptyPos(topNum, length);if (emptyPos != -1)topNum[emptyPos] = adj->vertexList[pos]->v;dfs(adj, topNum, length, pos);}
}


完整代码:

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <assert.h>
#define MAXVEX 100
#define MAXNUM 10
#define INFINITE 65525#define VTYPE char
#define QUETYPE EdgePtr
#define SORTTYPE int#define BOOLEAN int
#define TRUE 1
#define FALSE 0typedef struct EdgeNode {VTYPE v;VTYPE w;int weight;struct EdgeNode *next;
} Edge, *EdgePtr;typedef struct VertexNode {VTYPE v;int degree;EdgePtr firstEdge;
} Vertex, *VertexPtr;typedef struct {VertexPtr vertexList[MAXVEX];int vNum;int eNum;
} AdjGraph, *AdjGraphPtr;void freeAdj(AdjGraphPtr a);
EdgePtr createEdgeNode(VTYPE v, VTYPE w, int weight);
int getVertexPos(const AdjGraphPtr m, const VTYPE key);
void insertVertex(AdjGraphPtr adj, const VTYPE key);
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight);
void addEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight);
AdjGraphPtr createAdjGraph(VTYPE *v, const int v_length, int *e, const int e_length_1, const int e_length_2);
AdjGraphPtr createDirectedGraph(VTYPE *v, const int v_length, int *e, const int e_length_1, const int e_length_2);void print(int *a, int length);BOOLEAN isInTop(VTYPE *topNum, int length, VTYPE key) {for (int i = 0; i < length; i++) {if (topNum[i] == key) {return TRUE;}}return FALSE;
}int degreePos(AdjGraphPtr adj, VTYPE *topNum , int length) {int pos = -1;for (int i = 0; i < adj->vNum; i++) {if (adj->vertexList[i]->degree == 0) {if (isInTop(topNum, length, adj->vertexList[i]->v) == FALSE) {pos = i;return pos;}}}return pos;
}int getEmptyPos(VTYPE *topNum, int length) {//获得未使用的位置for (int i = 0; i < 5; i++) {if (topNum[i] == 0) {return i;}}return -1;
}int dfs(AdjGraphPtr adj, VTYPE *topNum, int length, int pos) {EdgePtr tmp = adj->vertexList[pos]->firstEdge;while (tmp != NULL) {VTYPE w = tmp->w;int w_pos = getVertexPos(adj, w);adj->vertexList[w_pos]->degree--;if (adj->vertexList[w_pos]->degree == 0)continue;if (isInTop(topNum, length, w) == FALSE) {int emptyPos = getEmptyPos(topNum, length);if(emptyPos != -1)topNum[emptyPos] = w;}dfs(adj, topNum, length, w_pos);tmp = tmp->next;}
}void topSort(AdjGraphPtr adj, int length) {VTYPE topNum[5];for (int i = 0; i < length; i++) {topNum[i] = 0;}for (int i = 0; i < length; i++) {int pos = degreePos(adj, topNum, length);if (pos == -1) {return;}int emptyPos = getEmptyPos(topNum, length);if (emptyPos != -1)topNum[emptyPos] = adj->vertexList[pos]->v;dfs(adj, topNum, length, pos);}
}void main() {int e[6][3] = {{ 'A', 'B', 3 },{ 'B', 'D', 1 },{ 'B', 'E', 5 },{ 'B', 'C', 6 },{ 'D', 'E', 7 },{ 'C', 'E', 6 },};const int e_length_1 = 6;const int e_length_2 = 3;VTYPE v[5] = { 'A','B','C','D','E' };const int v_length = 5;AdjGraphPtr adj = createDirectedGraph(v, v_length, e, e_length_1, e_length_2);topSort(adj, v_length);freeAdj(adj);
}void freeAdj(AdjGraphPtr a) {for (int i = 0; i < a->vNum; i++) {if (a->vertexList[i]->firstEdge != NULL) {EdgePtr tmp = a->vertexList[i]->firstEdge;while (tmp->next != NULL) {EdgePtr t = tmp;tmp = tmp->next;free(t);}free(tmp);}free(a->vertexList[i]);}free(a);
}EdgePtr createEdgeNode(VTYPE v, VTYPE w, int weight) {EdgePtr a = (EdgePtr)malloc(sizeof(Edge));memset(a, 0, sizeof(Edge));a->v = v;a->w = w;a->weight = weight;a->next = NULL;return a;
}int getVertexPos(const AdjGraphPtr m, const VTYPE key) {for (int i = 0; i < m->vNum; i++) {if (m->vertexList[i]->v == key)return i;}return -1;
}void insertVertex(AdjGraphPtr adj, const VTYPE key) {for (int i = 0; i < adj->vNum; i++) {if (adj->vertexList[i]->v == key)return;}VertexPtr vNode = (VertexPtr)malloc(sizeof(Vertex));memset(vNode, 0, sizeof(Vertex));vNode->v = key;vNode->firstEdge = NULL;adj->vertexList[adj->vNum] = vNode;adj->vNum++;
}void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight) {int pos_a = getVertexPos(adj, a);EdgePtr avex = createEdgeNode(a, b, weight);if (adj->vertexList[pos_a]->firstEdge == NULL) {adj->vertexList[pos_a]->firstEdge = avex;}else {EdgePtr tmp = adj->vertexList[pos_a]->firstEdge;while (tmp->next != NULL) {tmp = tmp->next;}tmp->next = avex;}int pos_b = getVertexPos(adj, b);adj->vertexList[pos_b]->degree++;
}void addEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight) {insertEdge(adj, a, b, weight);insertEdge(adj, b, a, weight);adj->eNum++;
}AdjGraphPtr createAdjGraph(VTYPE *v, const int v_length, int *e, const int e_length_1, const int e_length_2) {AdjGraphPtr adj = (AdjGraphPtr)malloc(sizeof(AdjGraph));memset(adj, 0, sizeof(AdjGraph));for (int i = 0; i < v_length; i++) {insertVertex(adj, v[i]);}for (int i = 0; i < e_length_1; i++) {VTYPE a = *(e + e_length_2 * i + 0);VTYPE b = *(e + e_length_2 * i + 1);int weight = *(e + e_length_2 * i + 2);addEdge(adj, a, b, weight);}return adj;
}AdjGraphPtr createDirectedGraph(VTYPE *v, const int v_length, int *e, const int e_length_1, const int e_length_2) {AdjGraphPtr adj = (AdjGraphPtr)malloc(sizeof(AdjGraph));memset(adj, 0, sizeof(AdjGraph));for (int i = 0; i < v_length; i++) {insertVertex(adj, v[i]);}for (int i = 0; i < e_length_1; i++) {VTYPE a = *(e + e_length_2 * i + 0);VTYPE b = *(e + e_length_2 * i + 1);int weight = *(e + e_length_2 * i + 2);insertEdge(adj, a, b, weight);}adj->eNum++;return adj;
}void print(int *a, int length) {for (int i = 0; i < length; i++) {printf("%d ", a[i]);}putchar('\n');
}

C语言 拓补排序 有向无环图相关推荐

  1. java 有向无环图 树_拓扑排序-有向无环图(DAG, Directed Acyclic Graph)

    条件: 1.每个顶点出现且只出现一次. 2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面. 有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说. 一 ...

  2. c语言 拓补排序源代码,拓扑排序C语言代码

    #include #include #include #include //----------------公共的----------------- #define TRUE 1 #define FA ...

  3. 有向无环图——AOV网及拓扑排序

    有向无环图--AOV网及拓扑排序 有向无环图 无环的有向图叫有向无环图,简称DAG图 其应用大致如下: 在工程计划和管理方面有着广泛而重要的应用 描述一项工程或系统的进行进程的有效工具 对整个工程和系 ...

  4. 有向无环图的应用——拓扑排序

    目录 一.什么是AOV网? 二.什么是拓扑排序? 2.1 拓扑排序的定义 2.2 拓扑排序的基本思想 三.拓扑排序算法的实现 3.1 算法思想 3.1.1 设置辅助数组indegree[ ] 3.1. ...

  5. 【BZOJ3036】绿豆蛙的归宿 拓补排序+概率

    [BZOJ3036]绿豆蛙的归宿 Description 随着新版百度空间的下线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿. 给出一个有向无环的连通图,起点为1终点为N,每条边都有一个长度. ...

  6. 士兵排队问题(拓补排序)(附简要拓补排序思想及算法)

    题目描述 有N个士兵(1<=N<=100),编号依次为1,2,...,N.队列训练时,指挥官要把士兵从高到矮排成一行,但指挥官只知道"1 比2 高,7 比 5高"这样的 ...

  7. 奖金(拓补排序的应用)

    谁应该高谁的入度++,并记录下谁比低的高(低的得出度),所以入度为零的就是最低的(好不公平),找出所有最低的,将他们算作一层,奖金++(算是拓补排序吧) #include<cstdio> ...

  8. HDU4324 - Triangle LOVE 拓补排序

    HDU4324 - Triangle LOVE : http://acm.showproblemhdu.edu.cn/.php?pid=4324 标准的拓补排序,上代码 : #include < ...

  9. leetcode *210. 课程表 II(拓补排序)(2020.5.17)

    [题目]*210. 课程表 II 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们 ...

  10. 51nod-生产口罩(拓补排序+DP)by zyz

    题目:生产口罩 链接:http://class.51nod.com/Classes/Problem.html#courseProblemId=1718&classId=129 //注:题目来自 ...

最新文章

  1. 2022-2028年中国老年旅游市场深度调研及开发战略研究报告
  2. linux进程VSZ(虚拟内存)
  3. sublime使用技巧(4)-- 其他技巧【持续更新】
  4. C语言18个经典问题答录
  5. Android 音频录制和播放问题
  6. 人工智能,不止于技术的革命--WOT2017全球创新技术峰会开幕
  7. Basler相机SDK相关问题收集与知识汇总
  8. scss-@extend
  9. Python工程笔记(1):轨迹与日志
  10. Javascript對表格的操作[知識積累帖]
  11. 2017级软件2班安卓应用开发课程主页
  12. 智能一代云平台(四十二):关于异常的一些事
  13. android,PHP解析JSON数组,JSONArray,JSONOject,乱码
  14. 【Matlab学习笔记】【函数学习】size参数
  15. 无法打开配置文件vmx_如何解决Windows照片查看器无法显示此图片
  16. IIC和SPI的异同
  17. 计算机教师课改先进个人,基础教育课程改革工作先进个人事迹
  18. 深信服2018春季招聘-研发卷编程题 - 题解
  19. css 根据手机屏幕适应页面高度
  20. windows 下 nginx 双向认证自签名证书配置

热门文章

  1. html5 导航栏置顶,html5导航栏横向
  2. win10任务栏无反应假死解决办法
  3. C# MES系统结构梳理
  4. 无法安装驱动此计算机,安装Windows系统时,提示“无法在此驱动器上安装Windows”...
  5. 如何面试软件工程师 看这篇就够了
  6. 知其然(1) 无法使用 DISTINCT, GROUP BY 等子句从视图中选择 ROWID 或采样
  7. http的ssl证书保姆级配置安装-多域名 免费ssl证书 解析 nginx配置
  8. 思维导图的绘制要点及使用GitMind工具快速制作思维导图
  9. APP手机设备模拟器在线测试工具Responsinator
  10. 华硕笔记本显示服务器不可用,华硕笔记本电脑开不了热点咋办