图论简单介绍
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
top
0 1 4 0
3
0
top=0 top
3
1
2
1
2
1
1
2
4
3
6
5
0
top
0
4 4
top
0
4 4
0
4 4
4 4
0
1
0
1
top
0
0
0
01ຫໍສະໝຸດ 111拓扑排序算法 typedef int datatype; typedef int vextype; typedef struct node /*边表结点定义*/ { int adjvex; struct node *next; } edgenode; typedef struct /*顶点表结点定义*/ { vextype vertex int id; edgenode *link } vexnode; vexnode dig[n];
为找出关键活动, 需要求各个活动的 e[k] 与 l[k],以判 别是否 l[k] == e[k]. 为求得e[k]与 l[k],需要先求得从源点V0到各个顶点Vi 的 Ve[i] 和 Vl[i]。
求Ve[i]的递推公式
从Ve[0] = 0开始,向前递推
i
Ve[ j ] max{ Ve[i ] dur ( Vi , V j ) },
检测有向环的一种方法是对AOV网络构造它的拓 扑有序序列。即将各个顶点 (代表各个活动) 排列 成一个线性有序的序列,使得AOV网络中所有应 存在的前驱和后继关系都能得到满足。 这种构造AOV网络全部顶点的拓扑有序序列的运 算就叫做拓扑排序。 如果通过拓扑排序能将AOV网络的所有顶点都排 入一个拓扑有序的序列中,则该AOV网络中必定 不会出现有向环;相反,如果得不到满足要求的 拓扑有序序列,则说明AOV网络中存在有向环, 此AOV网络所代表的工程是不可行的。
全部顶点均已输出,拓扑有序序列形成, 拓扑排序完成;或 图中还有未输出的顶点,但已跳出处理循 环。这说明图中还剩下一些顶点,它们都 有直接前驱,再也找不到没有前驱的顶点 了。这时AOV网络中必定存在有向环。
a
b
c
d
e
f
为了便于考察每个顶点的入度,在顶点表中增加 一个入度域,同时设置一个栈来存储所有入度为0 的 顶点。在进行拓扑排序之前,只要对顶点表扫描一遍 ,将所有入度为0 的顶点都推入栈中,一旦排序过程 中出现新的入度为0 的顶点,也同样将其推入栈中。
typedef struct node2 { vextype vertex; int id; edgenode1 *link; } vexnode1; vexnode1 dig[n];
/* /* /* /*
边表结点定义 */ 邻接点域 */ 权值 */ 链域 */
/*顶点表结点定义*/ /* 顶点信息 */ /* 入度 */ /* 边表头指针 */
例如,对学生选课工程图进行拓扑排序,得到的拓 扑有序序列为
C1 , C2 , C3 , C4 , C5 , C6 , C8 , C9 , C7 或 C1 , C8 , C9 , C2 , C5 , C3 , C4 , C7 , C6
进行拓扑排序的方法
输入AOV网络。令 n 为顶点个数。 1、在AOV网络中选一个没有直接前驱的顶 点(即此顶点入度为0), 并输出之; 2、从图中删去该顶点, 同时删去所有它发出 的有向边; 重复以上两步, 直到
while (p) { k=p->adjvex; dig[k].id--; if (dig[k].id==0) { dig[k].id=top; top=k; } p=p->next; } } if (m<n) printf(“\nThe network has a cycle\n”); }
算法分析 设AOV网有n个顶点,e条边。初始建立 入度为0 的顶点栈,要检查所有顶点一次 ,执行时间为O(n);排序中,若AOV网无回 路,则每个顶点入、出栈各一次,每个边 表结点被检查一次,执行时间为O(n+e), 所以总的时间复杂度为O(n+e)。
for (i=0;i<n;i++) ve[i]=0;
/*各事件最早发生时间置为0*/
for (i=0;i<n;i++)
if (dig[i].id==0) tpord[++rear]=i;
/*将入度为0的顶点入队*/
m=0; /*计数器初始化*/ while (front!=rear) /*队非空*/ { front++; j=tpord[front]; /*出队*/ m++; /*对出队的顶点个数计数*/ p=dig[j].link; /*指向出边表中顶点的下标*/ while (p) /*删去所有出边*/ { k=p->adjvex; dig[k].id--; /*入度减1*/ if (ve[j]+p->dut>ve[k]) ve[k]=ve[j]+p->dut; /*计算最早发生时间*/ if (dig[k].id==0) tpord[++rear]=k; /*新的入度为0的顶点入队*/ p=p->next; /*找下一条边*/ } }
图的基本概念 图的存储结构 图的遍历 最小生成树 最短路径 拓扑排序 关键路径
拓扑排序
计划、施工过程、生产流程、程序流程等都是 “工程”。除了很小的工程外,一般都把工程 分为若干个叫做“活动”的子工程。完成了这 些活动,这个工程就可以完成了。 例如,计算机专业学生的学习就是一个工程, 每一门课程的学习就是整个工程的一些活动。 其中有些课程要求先修课程,有些则不要求。 这样在有的课程之间有先后关系,有的课程可 以并行地学习。
l[k] = Vl[j] - dur(<i, j>)。 其中,dur(<i, j>)是完成ak 所需的时间。 时间余量 l[k] - e[k] 表示活动ak 的最早可能开始时间和最迟允许开始时间 的时间余量。l[k] == e[k]表示活动ak 是没有时间余量 的关键活动。显然,关键路径上的所有活动都是关键 活动。
6
16
v2
0 6 6 1 7 9
v7
16
2
18
v1
0
v5
4 4 1 7
7
v9
14 18 4
v3
5 6
v8
14
4
5 7 2
v4
8
v6
10
6
16
v2
0 6 6 4
v7
1 1
7
9
7
16 14
2
18
v1
0
v5
4
7
v9 v8
14
v3
5 6 5
4
18
4
2 7
v4
8 活动
v6
10
1-2 1-3 1-4 2-5 3-5 4-6 5-7 5-8 6-8 7-9 8-9
出边表
v1 v2 v3 v4 v5 v6
0 2 1 2 3 0
。。。
null 。。。
1
2
。。。
null 。。。
4
3
6
5
拓扑排序算法框架
1、扫描顶点表,将入度为0 的顶点入栈; 2、while ( 栈非空 ) { 将栈顶顶点v弹出并输出之; 检查v的出边,将每条出边<v,u>终点u的入度减1,
若u的入度变为0,则把u推入栈;
C1 C2 C3 C4 C5 C6 C7 C8 C9
高等数学 程序设计基础 离散数学 数据结构 高级语言程序设计 编译方法 操作系统 普通物理 计算机原理
C1, C3, C2 C5, C4, C1 C8
C2 C2 C4 C9
学生课程学习工程图
可以用有向图表示一个工程。在这种有向
图中,用顶点表示活动,用有向边<Vi, Vj> 表示活动的前后次序。Vi 必须先于活动Vj 进行。这种有向图叫做顶点表示活动的 AOV网络(Activity On Vertices)。 在AOV网络中,如果活动Vi 必须在活动Vj 之前进行,则存在有向边<Vi, Vj>, AOV 网络中不能出现有向回路,即有向环。在 AOV网络中如果出现了有向环,则意味着 某项活动应以自己作为先决条件。 因此,对给定的AOV网络,必须先判断它 是否存在有向环。
< Vi, Vj > S2, i = 1, 2, , n-1 其中, S2是所有从Vi指向顶点Vj 的有向边< Vi , Vj>的集合。 从Vl[n-1] = Ve[n-1]开始,反向递推
Vl[i ] min{ Vl[ j ] dur ( Vi , V j ) },
j
< Vi, Vj > S1, i = n-2, n-3, , 0 其中, S1是所有从顶点Vi 发出的有向边< Vi , Vj > 的集合。
e
l e-l
0
0 0
0
2 2
0
3 3
6
6 0
4
6 2
5
8 3
7
7 0
7
7 0
7
16
14
14 0
10 16 3 0
6
16
v2
0
6 6 1 7 9
v7
16
2 18
v1
0
v5
7 7 14
v9
18 4
v8
14
求关键路径的算法 typedef struct node1 { int adjvex; int dut; struct node1 *next; } edgenode1;
/* 邻接表 */
CRITICALPATH(vexnode1 dig[]) { int i,j,k,m;
int front=-1; rear=-1;
int tpord[n],vl[n],ve[n]; int l[maxsize],e[maxsize];
/*顺序队列首位指针置初值*/
edgenode1 *p;
} 3、若输出的顶点数小于n,则输出“有回路”;否则拓 扑 排序正常结束。
在算法具体实现时,上述链栈无须占有
额外的空间,而是利用顶点表中值为0 的入
度域来存放链栈的指针(用下标值模拟)。
因为顶点域中已经存入有相应的顶点,故入
栈时只需修改相应的指针。
1
2
4
3
6
5
0 2 1 2
0 2 1 2
top
0 2 1 1
TOPOSORT(vexnode dig[]) { int i,j,k,m=0,top=-1; edgenode *p; for (i=0;i<n;i++) if (dig[i].id==0) { dig[i].id=top; top=i; } while (top!=-1) { j=top; top=dog[top].id; printf(“%d\t”, dig[j].vertex+1); m++; p=dig[j].link;
(1) 完成整个工程至少需要多少时间(假设网络中没有 环).
(2) 为缩短完成工程所需的时间, 应当加快哪些活动.
在AOE网络中, 有些活动顺序进行,有些活动并 行进行。 从源点到各个顶点,以至从源点到汇点的有向路 径可能不止一条。这些路径的长度也可能不同。 完成不同路径的活动所需的时间虽然不同,但只 有各条路径上所有活动都完成了,整个工程才算 完成。 因此,完成整个工程所需的时间取决于从源点到 汇点的最长路径长度,即在这条路径上所有活动 的持续时间之和。这条路径长度最长的路径就叫 做关键路径(Critical Path)。
定义几个与计算关键活动有关的量:
事件Vi 的最早可能开始时间Ve(i)
是从源点V0 到顶点Vi 的最长路径长度。 事件Vi 的最迟允许开始时间Vl[i] 是在保证汇点Vn-1 在Ve[n-1] 时刻完成的前提 下,事件Vi 的允许的最迟开始时间。 活动ak 的最早可能开始时间 e[k] 设活动ak 在边< Vi , Vj >上,则e[k]是从源点 V0到顶点Vi 的最长路径长度。因此, e[k] = Ve[i]。 活动ak 的最迟允许开始时间 l[k] l[k]是在不会引起时间延误的前提下,该活动允 许的最迟开始时间。
这两个递推公式的计算必须分别在拓扑有序及逆拓扑有 序的前提下进行。 设活动ak (k = 1, 2, …, e)在带权有向边< Vi , Vj > 上, 它的 持续时间用dur (<Vi , Vj >) 表示,则有 e[k] = Ve[i]; l[k] = Vl[j] - dur(<Vi , Vj >);k = 1, 2, …, e。 这样就得到计算关键路径的算法。 计算关键路径时,可以一边进行拓扑排序一边计算各顶 点的Ve[i],并按拓扑有序的顺序对各顶点重新进行了编 号。算法在求Ve[i], i=0, 1, …, n-1时按拓扑有序的顺序计 算,在求Vl[i], i=n-1, n-2, …, 0时按逆拓扑有序的顺序计 算。
关键路径
如果在无有向环的带权有向图中 用有向边表示一个工程中的各项活动(Activity)
用边上的权值表示活动的持续时间(Duration)
用顶点表示事件(Event) 则这样的有向图叫做用边表示活动的网络,简称AOE (Activity On Edges)网络。 AOE网络在某些工程估算方面非常有用。例如,可以使 人们了解:
0 1 4 0
3
0
top=0 top
3
1
2
1
2
1
1
2
4
3
6
5
0
top
0
4 4
top
0
4 4
0
4 4
4 4
0
1
0
1
top
0
0
0
01ຫໍສະໝຸດ 111拓扑排序算法 typedef int datatype; typedef int vextype; typedef struct node /*边表结点定义*/ { int adjvex; struct node *next; } edgenode; typedef struct /*顶点表结点定义*/ { vextype vertex int id; edgenode *link } vexnode; vexnode dig[n];
为找出关键活动, 需要求各个活动的 e[k] 与 l[k],以判 别是否 l[k] == e[k]. 为求得e[k]与 l[k],需要先求得从源点V0到各个顶点Vi 的 Ve[i] 和 Vl[i]。
求Ve[i]的递推公式
从Ve[0] = 0开始,向前递推
i
Ve[ j ] max{ Ve[i ] dur ( Vi , V j ) },
检测有向环的一种方法是对AOV网络构造它的拓 扑有序序列。即将各个顶点 (代表各个活动) 排列 成一个线性有序的序列,使得AOV网络中所有应 存在的前驱和后继关系都能得到满足。 这种构造AOV网络全部顶点的拓扑有序序列的运 算就叫做拓扑排序。 如果通过拓扑排序能将AOV网络的所有顶点都排 入一个拓扑有序的序列中,则该AOV网络中必定 不会出现有向环;相反,如果得不到满足要求的 拓扑有序序列,则说明AOV网络中存在有向环, 此AOV网络所代表的工程是不可行的。
全部顶点均已输出,拓扑有序序列形成, 拓扑排序完成;或 图中还有未输出的顶点,但已跳出处理循 环。这说明图中还剩下一些顶点,它们都 有直接前驱,再也找不到没有前驱的顶点 了。这时AOV网络中必定存在有向环。
a
b
c
d
e
f
为了便于考察每个顶点的入度,在顶点表中增加 一个入度域,同时设置一个栈来存储所有入度为0 的 顶点。在进行拓扑排序之前,只要对顶点表扫描一遍 ,将所有入度为0 的顶点都推入栈中,一旦排序过程 中出现新的入度为0 的顶点,也同样将其推入栈中。
typedef struct node2 { vextype vertex; int id; edgenode1 *link; } vexnode1; vexnode1 dig[n];
/* /* /* /*
边表结点定义 */ 邻接点域 */ 权值 */ 链域 */
/*顶点表结点定义*/ /* 顶点信息 */ /* 入度 */ /* 边表头指针 */
例如,对学生选课工程图进行拓扑排序,得到的拓 扑有序序列为
C1 , C2 , C3 , C4 , C5 , C6 , C8 , C9 , C7 或 C1 , C8 , C9 , C2 , C5 , C3 , C4 , C7 , C6
进行拓扑排序的方法
输入AOV网络。令 n 为顶点个数。 1、在AOV网络中选一个没有直接前驱的顶 点(即此顶点入度为0), 并输出之; 2、从图中删去该顶点, 同时删去所有它发出 的有向边; 重复以上两步, 直到
while (p) { k=p->adjvex; dig[k].id--; if (dig[k].id==0) { dig[k].id=top; top=k; } p=p->next; } } if (m<n) printf(“\nThe network has a cycle\n”); }
算法分析 设AOV网有n个顶点,e条边。初始建立 入度为0 的顶点栈,要检查所有顶点一次 ,执行时间为O(n);排序中,若AOV网无回 路,则每个顶点入、出栈各一次,每个边 表结点被检查一次,执行时间为O(n+e), 所以总的时间复杂度为O(n+e)。
for (i=0;i<n;i++) ve[i]=0;
/*各事件最早发生时间置为0*/
for (i=0;i<n;i++)
if (dig[i].id==0) tpord[++rear]=i;
/*将入度为0的顶点入队*/
m=0; /*计数器初始化*/ while (front!=rear) /*队非空*/ { front++; j=tpord[front]; /*出队*/ m++; /*对出队的顶点个数计数*/ p=dig[j].link; /*指向出边表中顶点的下标*/ while (p) /*删去所有出边*/ { k=p->adjvex; dig[k].id--; /*入度减1*/ if (ve[j]+p->dut>ve[k]) ve[k]=ve[j]+p->dut; /*计算最早发生时间*/ if (dig[k].id==0) tpord[++rear]=k; /*新的入度为0的顶点入队*/ p=p->next; /*找下一条边*/ } }
图的基本概念 图的存储结构 图的遍历 最小生成树 最短路径 拓扑排序 关键路径
拓扑排序
计划、施工过程、生产流程、程序流程等都是 “工程”。除了很小的工程外,一般都把工程 分为若干个叫做“活动”的子工程。完成了这 些活动,这个工程就可以完成了。 例如,计算机专业学生的学习就是一个工程, 每一门课程的学习就是整个工程的一些活动。 其中有些课程要求先修课程,有些则不要求。 这样在有的课程之间有先后关系,有的课程可 以并行地学习。
l[k] = Vl[j] - dur(<i, j>)。 其中,dur(<i, j>)是完成ak 所需的时间。 时间余量 l[k] - e[k] 表示活动ak 的最早可能开始时间和最迟允许开始时间 的时间余量。l[k] == e[k]表示活动ak 是没有时间余量 的关键活动。显然,关键路径上的所有活动都是关键 活动。
6
16
v2
0 6 6 1 7 9
v7
16
2
18
v1
0
v5
4 4 1 7
7
v9
14 18 4
v3
5 6
v8
14
4
5 7 2
v4
8
v6
10
6
16
v2
0 6 6 4
v7
1 1
7
9
7
16 14
2
18
v1
0
v5
4
7
v9 v8
14
v3
5 6 5
4
18
4
2 7
v4
8 活动
v6
10
1-2 1-3 1-4 2-5 3-5 4-6 5-7 5-8 6-8 7-9 8-9
出边表
v1 v2 v3 v4 v5 v6
0 2 1 2 3 0
。。。
null 。。。
1
2
。。。
null 。。。
4
3
6
5
拓扑排序算法框架
1、扫描顶点表,将入度为0 的顶点入栈; 2、while ( 栈非空 ) { 将栈顶顶点v弹出并输出之; 检查v的出边,将每条出边<v,u>终点u的入度减1,
若u的入度变为0,则把u推入栈;
C1 C2 C3 C4 C5 C6 C7 C8 C9
高等数学 程序设计基础 离散数学 数据结构 高级语言程序设计 编译方法 操作系统 普通物理 计算机原理
C1, C3, C2 C5, C4, C1 C8
C2 C2 C4 C9
学生课程学习工程图
可以用有向图表示一个工程。在这种有向
图中,用顶点表示活动,用有向边<Vi, Vj> 表示活动的前后次序。Vi 必须先于活动Vj 进行。这种有向图叫做顶点表示活动的 AOV网络(Activity On Vertices)。 在AOV网络中,如果活动Vi 必须在活动Vj 之前进行,则存在有向边<Vi, Vj>, AOV 网络中不能出现有向回路,即有向环。在 AOV网络中如果出现了有向环,则意味着 某项活动应以自己作为先决条件。 因此,对给定的AOV网络,必须先判断它 是否存在有向环。
< Vi, Vj > S2, i = 1, 2, , n-1 其中, S2是所有从Vi指向顶点Vj 的有向边< Vi , Vj>的集合。 从Vl[n-1] = Ve[n-1]开始,反向递推
Vl[i ] min{ Vl[ j ] dur ( Vi , V j ) },
j
< Vi, Vj > S1, i = n-2, n-3, , 0 其中, S1是所有从顶点Vi 发出的有向边< Vi , Vj > 的集合。
e
l e-l
0
0 0
0
2 2
0
3 3
6
6 0
4
6 2
5
8 3
7
7 0
7
7 0
7
16
14
14 0
10 16 3 0
6
16
v2
0
6 6 1 7 9
v7
16
2 18
v1
0
v5
7 7 14
v9
18 4
v8
14
求关键路径的算法 typedef struct node1 { int adjvex; int dut; struct node1 *next; } edgenode1;
/* 邻接表 */
CRITICALPATH(vexnode1 dig[]) { int i,j,k,m;
int front=-1; rear=-1;
int tpord[n],vl[n],ve[n]; int l[maxsize],e[maxsize];
/*顺序队列首位指针置初值*/
edgenode1 *p;
} 3、若输出的顶点数小于n,则输出“有回路”;否则拓 扑 排序正常结束。
在算法具体实现时,上述链栈无须占有
额外的空间,而是利用顶点表中值为0 的入
度域来存放链栈的指针(用下标值模拟)。
因为顶点域中已经存入有相应的顶点,故入
栈时只需修改相应的指针。
1
2
4
3
6
5
0 2 1 2
0 2 1 2
top
0 2 1 1
TOPOSORT(vexnode dig[]) { int i,j,k,m=0,top=-1; edgenode *p; for (i=0;i<n;i++) if (dig[i].id==0) { dig[i].id=top; top=i; } while (top!=-1) { j=top; top=dog[top].id; printf(“%d\t”, dig[j].vertex+1); m++; p=dig[j].link;
(1) 完成整个工程至少需要多少时间(假设网络中没有 环).
(2) 为缩短完成工程所需的时间, 应当加快哪些活动.
在AOE网络中, 有些活动顺序进行,有些活动并 行进行。 从源点到各个顶点,以至从源点到汇点的有向路 径可能不止一条。这些路径的长度也可能不同。 完成不同路径的活动所需的时间虽然不同,但只 有各条路径上所有活动都完成了,整个工程才算 完成。 因此,完成整个工程所需的时间取决于从源点到 汇点的最长路径长度,即在这条路径上所有活动 的持续时间之和。这条路径长度最长的路径就叫 做关键路径(Critical Path)。
定义几个与计算关键活动有关的量:
事件Vi 的最早可能开始时间Ve(i)
是从源点V0 到顶点Vi 的最长路径长度。 事件Vi 的最迟允许开始时间Vl[i] 是在保证汇点Vn-1 在Ve[n-1] 时刻完成的前提 下,事件Vi 的允许的最迟开始时间。 活动ak 的最早可能开始时间 e[k] 设活动ak 在边< Vi , Vj >上,则e[k]是从源点 V0到顶点Vi 的最长路径长度。因此, e[k] = Ve[i]。 活动ak 的最迟允许开始时间 l[k] l[k]是在不会引起时间延误的前提下,该活动允 许的最迟开始时间。
这两个递推公式的计算必须分别在拓扑有序及逆拓扑有 序的前提下进行。 设活动ak (k = 1, 2, …, e)在带权有向边< Vi , Vj > 上, 它的 持续时间用dur (<Vi , Vj >) 表示,则有 e[k] = Ve[i]; l[k] = Vl[j] - dur(<Vi , Vj >);k = 1, 2, …, e。 这样就得到计算关键路径的算法。 计算关键路径时,可以一边进行拓扑排序一边计算各顶 点的Ve[i],并按拓扑有序的顺序对各顶点重新进行了编 号。算法在求Ve[i], i=0, 1, …, n-1时按拓扑有序的顺序计 算,在求Vl[i], i=n-1, n-2, …, 0时按逆拓扑有序的顺序计 算。
关键路径
如果在无有向环的带权有向图中 用有向边表示一个工程中的各项活动(Activity)
用边上的权值表示活动的持续时间(Duration)
用顶点表示事件(Event) 则这样的有向图叫做用边表示活动的网络,简称AOE (Activity On Edges)网络。 AOE网络在某些工程估算方面非常有用。例如,可以使 人们了解: