关于拓扑排序(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网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...
随机推荐
- ASP.NET Ajax简单的无刷新分页
最近练习了一些AJAX无刷新分页,写得比较简单,性能不知道怎么样,求大神指点,如有更好的分页提供,欢迎交流! 发话不多说了,直接上代码! 首先从网上下了一个JS分页,感觉挺好用的 (function( ...
- SQL IDENTITY(int,1,1) 用法
select IDENTITY(int,1,1) as SortID from tb_order 仅当 SELECT 语句中有 INTO 子句时,才能使用 IDENTITY 函数. select ID ...
- php验证码无法显示的原因
前段时间在调试程序的时候出现验证码无法打开的情况, 首先就要确定你已经开启了GD库!只要你不是低版本的PHP基本上这个是默认的!直接加上下面的代码先测试就可以! 如果不通过再查别的原因! 测试最后发现 ...
- blogs
http://blogs.msdn.com/b/tess/archive/2008/02/04/net-debugging-demos-information-and-setup-instructio ...
- 【学习笔记】【C语言】数据
1. 什么是数据 生活中时时刻刻都在跟数据打交道,比如体重数据.血压数据.股价数据等.在我们使用计算机的过程中,会接触到各种各样的数据,有文档数据.图片数据.视频数据,还有聊QQ时产生的文字数据.用迅 ...
- 20150216—winform中的DataGridView
DataGridView的主要作用是用来按列表来显示信息,其信息的数据源可以是SQL数据库,也可以是一个列表式的集合. DataGridView的位置:工具箱--数据--DataGridView.如下 ...
- WCF之服务元数据
服务元数据是用来获得服务的EndPoint的信息,也就是它的ABC. 服务有两种方案可以发布自己的元数据. 一种是基于HTTP-GET协议提供元数据: 一种是元数据交换方式,它往往使用一个专门的终结点 ...
- 异常getaddrinfo enotfound
在看NodeJS开发指南这本书时,书中的一个例子,讲解http.request的.代码如下: var http = require('http'); var querystring = require ...
- java springmvc Log4j filter等(稍微完善一下项目)
仅供参考-接上文 springmvc 1.设置Log4jConfigListener日志监听(可以为开发调试.发布后运行的意外调试.等) 在src/main/resources目录下新建log4j. ...
- 简单工厂(Simple Pattern)模式
一.简单工厂(Simple Factory)模式 Simple Factory 模式根据提供给它的数据,返回几个可能类中的一个类的实例.通常它返回的类都有一个公共的父类和公共的方法. Simple F ...