题目:拓扑排序算法的基本思想

一、基本概念

拓扑排序是一个非常容易理解的概念。我们要回忆一下入度这个概念。

我们想象这样一个图,里面只有两个结点A和B,且只有一条从A指向B的边。那么此时,我们称A的入度为0,B的入度为1。

也就是说,某个结点被几个结点指向,那么它的入度就是几。

所谓拓扑排序,就是每次出队的结点入度都为0。这样一直循环下去,就能将一个图中的结点进行排序。

二、代码实现

(1)初步框架

1.头文件:

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

2.规定一下点的最大个数(这里以9个点为例):

#define MaxVertex 9

3.定义结点的结构体:

由于用的是邻接表,所以普通的结点和头结点要分开定义。

typedef struct LNode{int nextVertex;struct LNode *next;
}*Node;

4.定义头结点的结构体:

这里存放的是入度。

struct HeadNode{int inDegree;struct LNode *next;
};

 5.定义邻接表结构体:

typedef struct Adj{int vertexCount;int edgeCount;struct HeadNode vertex[MaxVertex];
}*Graph;

(2) 邻接表的基本操作:

1.创建一个邻接表:

Graph createGraph(){Graph graph = (Graph)malloc(sizeof(struct Adj));graph -> vertexCount = graph -> edgeCount = 0;return graph;
}

2.插入点:

void addVertex(Graph graph){graph -> vertex[graph -> vertexCount].inDegree = 0;graph -> vertex[graph -> vertexCount].next = NULL;graph -> vertexCount++;
}

3.插入边:

void addEdge(Graph graph, int a, int b){Node node = graph -> vertex[a].next;//newNode为新建的结点,存放b,待插入Node newNode = (Node)malloc(sizeof(struct LNode));newNode -> nextVertex = b;newNode -> next = NULL;//如果node为空,也就是说这个结点之前没有指向任何其他结点,那么直接插入即可if(node == NULL) graph -> vertex[a].next = newNode; else{//否则一直向后找do{if(node -> nextVertex == b) return ; //如果发现a已经指向b了,直接结束if(node -> next) node = node -> next; //如果node还有下一个元素,就继续遍历else break; //已经找到最后一个了,跳出循环}while(1);node -> next = newNode; //在最后一个结点后插入即可}graph -> vertex[b].inDegree++; //b的入度加1graph -> edgeCount++; //总边数加1
}

(3)拓扑排序函数:

首先我们定义一个队列,将表中所有入度为0的结点入队。然后进入while循环,从队列的第一个元素开始打印出队,并更新删除该结点后剩余结点的入度。如果有新入度为0的结点,就将其入队。这样反复操作下去,我们就完成了排序。

void topologicalSort(Graph graph){int queue[MaxVertex];int front = 0, rear = 0;for(int i = 0; i < MaxVertex; i++){if(graph -> vertex[i].inDegree == 0){queue[rear++] = i;}}while(front != rear){int v = queue[front++];if(graph -> vertex[v].next == NULL && front == rear){printf("%d", v);break;}printf("%d -> ", v);Node node = graph -> vertex[v].next;while(node){int w = node -> nextVertex;if(--graph -> vertex[w].inDegree == 0){queue[rear++] = node -> nextVertex;}node = node -> next;}}
}

三、测试效果

int main(){Graph graph = createGraph();for(int i = 0; i < 4; i++){addVertex(graph);}addEdge(graph, 3, 0);addEdge(graph, 3, 2);addEdge(graph, 0, 1);addEdge(graph, 0, 2);topologicalSort(graph);return 0;
}

运行结果:

四、完整代码

#include <stdio.h>
#include <stdlib.h>#define MaxVertex 4typedef struct LNode{int nextVertex;struct LNode *next;
}*Node;struct HeadNode{int inDegree;struct LNode *next;
};typedef struct Adj{int vertexCount;int edgeCount;struct HeadNode vertex[MaxVertex];
}*Graph;Graph createGraph(){Graph graph = (Graph)malloc(sizeof(struct Adj));graph -> vertexCount = graph -> edgeCount = 0;return graph;
}void addVertex(Graph graph){graph -> vertex[graph -> vertexCount].inDegree = 0;graph -> vertex[graph -> vertexCount].next = NULL;graph -> vertexCount++;
}void addEdge(Graph graph, int a, int b){Node node = graph -> vertex[a].next;//newNode为新建的结点,存放b,待插入Node newNode = (Node)malloc(sizeof(struct LNode));newNode -> nextVertex = b;newNode -> next = NULL;//如果node为空,也就是说这个结点之前没有指向任何其他结点,那么直接插入即可if(node == NULL) graph -> vertex[a].next = newNode; else{//否则一直向后找do{if(node -> nextVertex == b) return ; //如果发现a已经指向b了,直接结束if(node -> next) node = node -> next; //如果node还有下一个元素,就继续遍历else break; //已经找到最后一个了,跳出循环}while(1);node -> next = newNode; //在最后一个结点后插入即可}graph -> vertex[b].inDegree++; //b的入度加1graph -> edgeCount++; //总边数加1
}void topologicalSort(Graph graph){int queue[MaxVertex];int front = 0, rear = 0;for(int i = 0; i < MaxVertex; i++){if(graph -> vertex[i].inDegree == 0){queue[rear++] = i;}}while(front != rear){int v = queue[front++];printf("%d -> ", v);Node node = graph -> vertex[v].next;while(node){int w = graph -> vertex[node -> nextVertex].inDegree;if(--w == 0){queue[rear++] = node -> nextVertex;}node = node -> next;}}
}int main(){Graph graph = createGraph();for(int i = 0; i < 4; i++){addVertex(graph);}addEdge(graph, 3, 0);addEdge(graph, 3, 2);addEdge(graph, 0, 1);addEdge(graph, 0, 2);topologicalSort(graph);return 0;
}

南京工业大学2023数据结构复习题简析【编程题5】相关推荐

  1. 南京工业大学2023数据结构复习题简析【编程题2】

    题目:循环链表中结点的基本操作 考虑到没有说明是单循环链表还是双循环链表,秉持准备充分的原则,我们采用双向循环链表来完成这个问题. 一.初步框架 1.头文件: #include <stdio.h ...

  2. 南京工业大学2023数据结构复习题简析【编程题3】

    题目:图的邻接矩阵表示法 注意:本文中所面向的图是有向图 一.初步框架 1.头文件: #include <stdio.h> #include <stdlib.h> 2.定义邻接 ...

  3. 南京工业大学2023数据结构复习题简析【编程题4】

    题目:Floyd算法求取图中每一对顶点之间的最短距离 一.快速回忆 Q1:Floyd算法的作用是什么? 答:那必然是求取图中每一对顶点之间的最短距离(见题目). Q2:Floyd算法需要基于什么来实现 ...

  4. “四非”高校南京工业大学,17天内三连击Nature、Science!实为深藏不露

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者 | 维克多 <Nature>和<Science>杂志创刊已有百余年,作为 ...

  5. 南工计算机调剂,南京工业大学2021年硕士研究生调剂公告

    一.申请条件 1.申请调剂考生需符合<教育部关于印发<2021年全国硕士研究生招生工作管理规定>的通知>(教学函( 2020 )8号)要求. 2.非全日制硕士研究生需以定向就业 ...

  6. 【调剂】南京信息工程大学2023年中外合作计算机,电子信息都招!

    公众号[计算机与软件考研]每天都会发布最新的计算机考研调剂信息! 点击公众号界面左下角的调剂信息或者公众号回复"调剂"是计算机/软件等专业的所有调剂信息集合,会一直更新的. 南京信 ...

  7. 南工大计算机录取分数线,南京工业大学2016年录取分数线

    南京工业大学2016年录取分数线 省份  批次  科类  最高分  最低分  辅助排序分 河北  艺术提前批  艺术  712  550 山西  艺术提前批  艺术  687  589  361 内蒙 ...

  8. 河南工业大学c语言考试题库,c语言题库(编程)河南工业大学 河工大 c语言期末考试题库...

    c语言题库(编程)河南工业大学 河工大 c语言期末考试题库 (27页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 C语言题库编程河南工业 ...

  9. 南京工业大学python考试期末题库_大学慕课用Python玩转数据期末考试查题公众号答案...

    大学慕课用Python玩转数据期末考试查题公众号答案 更多相关问题 雪松的树形为 (5.0分) - Do you think I can borrow your bike for a few hour ...

最新文章

  1. 虚拟服务器nodejs项目部署打包,nodejs+express搭建服务器及vue项目部署打包
  2. Android源码学习之工厂方法模式应用
  3. Sharepoint学习笔记—Site Definition系列-- 3、创建ListDefinition
  4. Centos7下安装Python3.5
  5. 串的模式匹配(BF算法)
  6. 新来的前端小姐姐问:Vue路由history模式刷新页面出现404问题
  7. Intel Core Enhanced Core架构/微架构/流水线 (14) - 存储器/内存读写 Memory Load/Store
  8. XX基金 机器学习平台使用情况访谈总结
  9. nest.js实战之集成Linkedin登录
  10. oracle常用查询语句
  11. C++ 中cin的输入原理及字符串(string、char[])输入问题
  12. C语言求阶乘与阶乘和
  13. 透视相机(PerspectiveCamera)
  14. 使用DreamweaverMX2004的搜索替换功能提高工作效率。
  15. 幼麟棋牌登录socket服务器分析
  16. 语言表达的6c原则是指什么,第二讲 BEC写作的语言、语法、组织和文体
  17. 几十年前的老旧照片如何修复?还不知道旧照片怎么恢复清晰吗?
  18. 实验02-微信公众号编辑模式应用
  19. 职场新境之“甩手组”
  20. Java 创建并用应用幻灯片母版

热门文章

  1. Win10更改注册表win defend键值提示无法更改所有者
  2. android时间接收器,android – 在飞机模式关闭/打开后,广播接收器在onReceive()中接收的时间太长...
  3. Fiddler 工作原理和使用
  4. 读 在浮躁的年代里做学问..
  5. 烧水壶java代码_JAVA代码—算法基础:水壶分水的问题
  6. mysql tinyint
  7. springboot毕设项目多层级架构的工程项目安全监管系统的设计与实现tx75u(java+VUE+Mybatis+Maven+Mysql)
  8. uC-OS2 V2.93 STM32L476 移植:系统移植篇
  9. Java二分法查找最大值
  10. 机器人创客加盟的几点建议