关于拓扑排序(topologicalsort)
假设我们有一组任务要完成,并且有些任务要在其它任务完成之后才能开始,所以我们必须非常小心这些任务的执行顺序。
如果这些任务的执行顺序足够简单的话,我们可以用链表来存储它们,这是一个很好的方案,让我们可以准确知道任务的执行顺序。问题是有时候不同任务之间的关系是非常复杂的,有些任务依赖于两个甚至更多的任务,或者反过来很多任务依赖自己。
因此我们不能通过链表或者树的数据结构来对这个问题建模。对这类问题唯一合理的数据结构就是图。我们需要哪种图呢?很显然,我们需要有向图来描述这种关系,而且是不能循环的有向图,我们称之为有向无环图。要通过拓扑排序对图形进行排序,这些图必须是不能循环和有向的。为什么这些图不能循环呢?答案很明显,如果图形是循环的,我们无法知道哪个任务该优先执行,也不可能对任务进行排序。现在我们一要做的是对图中的每个节点排序,组成一条条边(u,v),u在v之前执行。然后我们就可以得到所有任务的线性顺序,并按这种顺序执行任务就一切都OK了。
例如,下面的图的一个拓扑排序是“5 4 2 3 1 0”。一个图可以有多个拓扑排序。
另一个拓扑排序是“4 5 2 3 1 0”。拓扑排序的第一个顶点总是入度为0。

-------------------------------------------------------------------------------------------------------------------------------------------
1.思想先找一个入度为零的访问
接着把它和它的路线删除.....................
但我们并没有真正把它删除,把访问过的入队即可并标记, 随后把与它相邻的元素入度减一即可!!!!
------------------------------
//topologicalsort 排序的实现 容器队列 #include <cstdio>
#include <cstdlib>
//#define _OJ_
#define maxsize 100
int visit[100]; //用来标记已被访问的元素
typedef struct Queue1
{
int top;
int base;
int *elem; //定义队列尊循先进先出的原则
} Queue1, *Queue; typedef struct Graph1
{
int nv;
int ne;
int G[100][100];
} Graph1, *Graph; Queue
creat_Queue(void)
{
Queue q;
q = (Queue) malloc (sizeof(Queue1));
q->elem = (int*) malloc (sizeof(int) * maxsize);
q->top = q->base = 0;
return q;
} int
isempty(Queue q)
{
if(q->top == q->base)
return 1;
else
return 0;
} void
Enqueue(Queue q, int data)
{
q->elem[q->top++] = data;
} int
Dequeue(Queue q)
{
return q->elem[q->base++];
} Graph
creat_Graph(void)
{
int v1, v2, i, j;
Graph g;
g = (Graph) malloc (sizeof(Graph1));
scanf("%d %d", &(g->nv), &(g->ne));
for(i = 1;i <= g->nv; i++) {
for(j = 1;j <= g->nv; j++) {
g->G[i][j] = 0;
}
} for(i = 1;i <= g->ne; i++) {
scanf("%d %d", &v1, &v2);
g->G[v1][v2] = 1;
} return g;
} int
Topologicalsort(Graph g)
{
Queue q;
int i, j, i1, cnt = 0;
int indegree[100];
q = creat_Queue(); for(i = 1;i <= g->nv ; i++) {
indegree[i] = 0; //用一个临时数组来记录入度即每一列非零元素
for(j = 1;j <= g->nv; j++) {
if(g->G[j][i] != 0) ++indegree[i];
}
if(indegree[i] == 0) {Enqueue(q, i); visit[i] = 1;}
} //度为零那么入队并标记 while (isempty(q) != 1) {
i1 = Dequeue(q); printf("i1 == %d\n", i1); cnt++;//cnt用于记录走过的元素
for(i = 1;i <= g->nv; i++) { //把与出队相邻的元素入度减一
if(g->G[i1][i] != 0) indegree[i]--;
if(indegree[i] == 0 && visit[i] == 0) {Enqueue(q, i); visit[i] = 1;}
}
} if(cnt < g->nv) printf("error\n"); //若从cnt< g->nv者出错表示图中有回路
} // void
// print(void)
// {
// int i, j, t;
// for(i = 1;i < n - 1; i++) {
// printf("%d ", visit1[i]);
// }
// printf("%d\n", visit1[n - 1]);
// } int main(int argc, char const *argv[]) {
#ifndef _OJ_ //ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif int i, j;
Graph g;
g = creat_Graph();
for(i = 1; i <= g->nv; i++)
visit[i] = 0;
Topologicalsort(g); return 0;
}
输入:
6 7
1 2
2 3
1 5
2 4
3 6
5 4
4 6
输出:
i1 == 1
i1 == 2
i1 == 5
i1 == 3
i1 == 4
i1 == 6
-----------------------------------------------------------------------------------------------------------------------队列实现
---------------------------------------------------------------------------------------------------------------------------------------
//top 排序的实现 容器栈(正确) #include <cstdio>
#include <cstdlib>
//#define _OJ_
#define maxszie 100 int visit[100];
typedef struct stack1
{
int top;
int base;
int *elem;
} stack1, *stack; typedef struct Graph1
{
int nv;
int ne;
int G[100][100];
} Graph1, *Graph; stack
creat_stack(void)
{
stack s;
s = (stack) malloc (sizeof(stack1));
s->elem = (int*) malloc (sizeof(int) * maxszie);
s->top = s->base = 0;
return s;
} int
isempty(stack s)
{
if(s->top == s->base)
return 1;
else
return 0;
} void
push(stack s, int data)
{
s->elem[s->top++] = data;
} int
pop(stack s)
{
return s->elem[--s->top];
} Graph
creat_Graph(void)
{
int v1, v2, i, j;
Graph g;
g = (Graph) malloc (sizeof(Graph1));
scanf("%d %d", &(g->nv), &(g->ne));
for(i = 1;i <= g->nv; i++) {
for(j = 1;j <= g->nv; j++) {
g->G[i][j] = 0;
}
} for(i = 1;i <= g->ne; i++) {
scanf("%d %d", &v1, &v2);
g->G[v2][v1] = 1;
} return g;
} void
Topologicalsort(Graph g)
{
stack s;
int i, j, i1, cnt = 0;
int indegree[100];
s = creat_stack();
for(i = 1;i <= g->nv ; i++) {
indegree[i] = 0;
for(j = 1;j <= g->nv; j++) {
if(g->G[j][i] != 0) ++indegree[i];
}
if(indegree[i] == 0) {push(s, i); visit[i] = 1;}
} while (isempty(s) != 1) {
i1 = pop(s); printf("i1 == %d ", i1); cnt++;
for(i = 1;i <= g->nv; i++) {
if(g->G[i1][i] != 0) indegree[i]--;
if(indegree[i] == 0 && visit[i] == 0) {push(s, i); visit[i] = 1;}//printf("i2=%d\n", i);}
}
} if(cnt < g->nv) printf("error\n");
else printf("ok\n");
} int main(int argc, char const *argv[]) {
#ifndef _OJ_ //ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif int i;
Graph g;
g = creat_Graph();
for(i = 1; i <= g->nv; i++)
visit[i] = 0;
Topologicalsort(g); return 0;
}
-----------------------------------------------------------------------------------------------------------------------------
输入:
6 7
1 2
2 3
1 5
2 4
3 6
5 4
4 6
输出:
i1 == 6 i1 == 4 i1 == 5 i1 == 3 i1 == 2 i1 == 1 ok
-----------------------------------------------------------------------------------------------------------------------栈的实现
栈的实现和队列的实现其实是一样的,,不过一个是先进先出,,一个先进后出,,so答案有所出入,,不过原理都一样!!!
关于拓扑排序(topologicalsort)的更多相关文章
- 拓扑排序(TopologicalSort)算法
拓扑排序算法应用: 有些事情做都需要按照流程的去做,比如你准备约你小女友去影院看速度与激情7大片,首先你想的是我怎么到达影院,然后达到影院,你可以先买票,或者等小女友来了一起买票,然后一起进电影大厅. ...
- 【LeetCode】拓扑排序 topological-sort(共5题)
[207]Course Schedule [210]Course Schedule II [269]Alien Dictionary [329]Longest Increasing Path in a ...
- 算法与数据结构(七) AOV网的拓扑排序
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...
- 拓扑排序(三)之 Java详解
前面分别介绍了拓扑排序的C和C++实现,本文通过Java实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处 ...
- 拓扑排序(二)之 C++详解
本章是通过C++实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处:http://www.cnblogs. ...
- POJ1094 拓扑排序
问题:POJ1094 本题考查拓扑排序算法 拓扑排序: 1)找到入度为0的点,加入已排序列表末尾: 2)删除该点,更新入度数组. 循环1)2)直到 1. 所有点都被删除,则找到一个拓扑 ...
- hdu4324 Triangle LOVE (拓扑排序)
这是一道最简单的拓扑排序题,好久没看这个算法了! 有点生疏了! 后附上百度的资料; #include<stdio.h> #include<string.h> int in[50 ...
- C++编程练习(12)----“有向图的拓扑排序“
设G={V,E}是一个具有 n 个顶点的有向图,V中的顶点序列 v1,v2,......,vn,满足若从顶点 vi 到 vj 有一条路径,则在顶点序列中顶点 vi 必在顶点 vj 之前.则称这样的顶点 ...
- 算法与数据结构(七) AOV网的拓扑排序(Swift版)
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...
随机推荐
- 每天一道LeetCode--434. Number of Segments in a String
Count the number of segments in a string, where a segment is defined to be a contiguous sequence of ...
- Part 67 to 70 Talking about method parameters in C#
Part 67 Optional parameters in c# Part 68 Making method parameters optional using method overloadin ...
- 使用jquery插件报错:TypeError:$.browser is undefined的解决方法
关于$.browser browser就是用来获取浏览器基本信息的. jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.sup ...
- 关于datatable转换datatime类型的问题
今天转换datatable 属性值的时候出错: DataTable dt_1 = new DataTable();dt_1 = new BLL.auction().GetList_pmh(top, _ ...
- HTML特殊字符编码大全
HTML特殊字符编码大全:往网页中输入特殊字符,需在html代码中加入以&开头的字母组合或以&#开头的数字.下面就是以字母或数字表示的 特殊符号大全 ´ © © > > µ ...
- 判断Featureclass的类型
一个Featureclass可以是Shapefile Feature Class.Personal Geodatabase Feature Class.File Geodatabase Feature ...
- 十个最常见的Java字符串问题
翻译自:Top 10 questions of Java Strings 1.怎样比较字符串?用”==”还是用equals()? 简单地说,”==”测试两个字符串的引用是否相同,equals()测试两 ...
- Linux驱动编程--基于I2C子系统的I2C驱动的Makefile
ifeq ($(KERNELRELEASE),) KERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd) TEST = ...
- 《自动共享LDAP用户并且访问其家目录》RHEL6
实验的目的: 实现ldap服务器上的ldap用户被客户端访问,自动挂载到客户端,并且可以访问ldap用户的家目录. 服务端: 1.只需要配置文件: Iptables –F 关闭selinu ...
- NSS_04 extjs中grid接收datetime类型参数列
今天在做用户列表时发现, asp.net mvc3的控制器在返回JsonResult结果时, 会把对象内的DateTime类型成员,解析为类似于\/Date(1238606590509)\/的格式 , ...