假设我们有一组任务要完成,并且有些任务要在其它任务完成之后才能开始,所以我们必须非常小心这些任务的执行顺序。
如果这些任务的执行顺序足够简单的话,我们可以用链表来存储它们,这是一个很好的方案,让我们可以准确知道任务的执行顺序。问题是有时候不同任务之间的关系是非常复杂的,有些任务依赖于两个甚至更多的任务,或者反过来很多任务依赖自己。
因此我们不能通过链表或者树的数据结构来对这个问题建模。对这类问题唯一合理的数据结构就是图。我们需要哪种图呢?很显然,我们需要有向图来描述这种关系,而且是不能循环的有向图,我们称之为有向无环图。要通过拓扑排序对图形进行排序,这些图必须是不能循环和有向的。为什么这些图不能循环呢?答案很明显,如果图形是循环的,我们无法知道哪个任务该优先执行,也不可能对任务进行排序。现在我们一要做的是对图中的每个节点排序,组成一条条边(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)的更多相关文章

  1. 拓扑排序(TopologicalSort)算法

    拓扑排序算法应用: 有些事情做都需要按照流程的去做,比如你准备约你小女友去影院看速度与激情7大片,首先你想的是我怎么到达影院,然后达到影院,你可以先买票,或者等小女友来了一起买票,然后一起进电影大厅. ...

  2. 【LeetCode】拓扑排序 topological-sort(共5题)

    [207]Course Schedule [210]Course Schedule II [269]Alien Dictionary [329]Longest Increasing Path in a ...

  3. 算法与数据结构(七) AOV网的拓扑排序

    今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...

  4. 拓扑排序(三)之 Java详解

    前面分别介绍了拓扑排序的C和C++实现,本文通过Java实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处 ...

  5. 拓扑排序(二)之 C++详解

    本章是通过C++实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处:http://www.cnblogs. ...

  6. POJ1094 拓扑排序

    问题:POJ1094   本题考查拓扑排序算法   拓扑排序:   1)找到入度为0的点,加入已排序列表末尾: 2)删除该点,更新入度数组.   循环1)2)直到 1. 所有点都被删除,则找到一个拓扑 ...

  7. hdu4324 Triangle LOVE (拓扑排序)

    这是一道最简单的拓扑排序题,好久没看这个算法了! 有点生疏了! 后附上百度的资料; #include<stdio.h> #include<string.h> int in[50 ...

  8. C++编程练习(12)----“有向图的拓扑排序“

    设G={V,E}是一个具有 n 个顶点的有向图,V中的顶点序列 v1,v2,......,vn,满足若从顶点 vi 到 vj 有一条路径,则在顶点序列中顶点 vi 必在顶点 vj 之前.则称这样的顶点 ...

  9. 算法与数据结构(七) AOV网的拓扑排序(Swift版)

    今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...

随机推荐

  1. CSS之拖拽1

    PageX:鼠标在页面上的位置,从页面左上角开始,即是以页面为参考点,不随滑动条移动而变化. clientX:鼠标在页面上可视区域的位置,从浏览器可视区域左上角开始,即是以浏览器滑动条此刻的滑动 到的 ...

  2. WCF之绑定

    NameSpace+Name作为服务元数据的唯一标示.BindingElement描述Binding的特征. 绑定表示通信信道的配置,定义C/S间的协议. 分为:传输信道(TCP,HTTP…),消息编 ...

  3. Session State Pattern会话状态模式

    Client Session State 客户会话状态. 在Client端保存会话状态. 运行机制 Client在每次请求时会把所有的会话数据传给Server,Server在响应时把所有的会话状态传给 ...

  4. [javascript|基本概念|一元操作符]学习笔记

    只操作一个值的操作符 递增/递减操作符 前置型/后置型 前置型:操作符位于操作数前面 e.g.: var a = 30; ++a; 等同于 var a = 30; a = a + 1; --> ...

  5. const type& 与 type& 的区别

    const type& 与 type& 是C/C++编程中容易混淆的两个知识点,现在以 cont int& 与 int& 为例讲解: 1.int& 讲解 int ...

  6. TOMCAT内存大小调整

    Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个java虚拟机.JAVA程序启动时JVM都会分配一个初始内存和最大内存给这个应用程序.这个初始内存和最大内存在一定程度都会 ...

  7. SQLServer数据库表中将指定列分组转一行

    不说明,直接看代码: --1. 创建表,添加测试数据 CREATE TABLE #test(code varchar(50), [values] varchar(10)) INSERT #test S ...

  8. centos 普通用户添加sudo权限

    本文介绍下,在centos中为普通用户添加sudo权限的方法,供大家学习参考. 在centos中为普通用户增加sudo权限的简单方法,大家参考下. 1,修改/etc/sudoers文件,必须为visu ...

  9. php中json_encode中文编码问题分析

    众所周知使用json_encode可以方便快捷地将对象进行json编码,但是如果对象的属性中存在着中文,问题也就随之而来了.json_encode会将中文转换为unicode编码例如:'胥'经过jso ...

  10. js javascript:void(0) 真正含义

    我想使用过ajax的都常见这样的代码:<a href="javascript:doTest2();void(0);">here</a>但这儿的void(0) ...