当前位置:文档之家› 数据结构-拓扑排序和最短路径

数据结构-拓扑排序和最短路径


拓扑排序---方法2
void DFS-T(Graph G, int v) {
// 从顶点v出发,深度优先搜索遍历连通图 G
visited[v] = TRUE; for(w=FirstAdjVex(G, v); w>=0; w=NextAdjVex(G,v,w)) {if (!visited[w]) DFS-T(G, w);}
4)重复2,3,直到所有的顶点都在S中
Dijkstra算法
如何保存V0到V的路径? 1、保存V0到V的路径上的顶点(即:不保存 边和顶点之间的顺序) 2、存储结构:n×n的矩阵p 3、矩阵的第V行表示V0到V的路径上顶点 如果顶点W在路径上,则p[v][w]=TRUE 否则,p[v][w]=FALSE
删除顶点及以它为尾的弧
拓扑排序---算法
Status ToplogicalSort(ALGragh G){ FindInDegree(G, indegree); InitStack(S); for(i=0;i<G.vexnum;i++){if(!indegree[i]) push(S,i);} count=0; //对输出顶点计数 while (!EmptyStack(S)) {
Dijkstra算法
用反证法:
假设存在W S V0-->W-->Vk
(V0-->W中的顶点都在S中)
因为V0 --> W 比 V0--> Vk短 那么,我们就会选择W作为Vk,而不会选择 Vk,矛盾。
Dijkstra算法
路径的形式一定为: V0->Vi1->Vi2…->Vip->Vk
Vi1,Vi2 ……,Vip ∈ S V0到Vk的最短路径是V0到Vip的最短路径 + Vip到Vk的边
v1 源点
v2

Dijkstra算法
1、长度最短的路径 V5 V0
10 30 10
V4
20
V1 V2
V3
Dijkstra算法
2、假设已经求出了V0到V1至Vk-1的最短路径 即:S={V0, V1, …,Vk-1} 3、求下一条最短路径,终点为Vk(不在S中) V0 --> Vk 则该路径上的顶点一定都在S中
Dijkstra算法讨论
4、和Prim算法有相似和不同的地方 都是从一个顶点开始 都有一个距离数组D
都有一个顶点是否已经被选取的标志
Dijkstra算法讨论
a
18 19
b
12
5
a c
3
14
b e
16 8
5
14 16
7
c
3
e
8
g
27
d f
21
g
f
d
21
Prim算法产生的最小生成树67
Dijkstra算法讨论
…………
}
}
Dijkstra算法实现
void ShortestPath_DIJ(MGraph G, int v0,PathMatrix &P, ShortestPathTable &D){ for(w=0;w<G.vexnum;++w){ if(!final[w]&&(min+G.arcs[v][w]<D[w])){ D[w]=min+G.arcs[v][w];//修改距离 p[w]=p[v];//修改路径 p[w][w]=TRUE; }// if }//for }// void
h e 退出DFS函数顺序:
拓扑排序---方法2
结论:
最先退出DFS函数的顶点是出度为零的顶点,为拓 扑排序序列中最后一个顶点。 因此,按退出DFS函数的先后记录下来的顶点序列 即为逆向的拓扑排序序列。
拓扑排序---方法2
void DFS-ToplogicalSort (Graph G, int v) {//如何确定v for (v=0; v<G.vexnum; ++v) visited[v] = FALSE; // 访问标志数组初始化 InitStack(S);//存放顶点,按照出DFS的次序 for (v=0; v<G.vexnum; ++v) { if (!visited[v]) DFS-T(G, v); // 对尚未访问的顶点调用DFS } while(!Empty(S)){//输出拓扑排序的结果 Pop(S, v); printf(“%d”, v)} }
课堂练习
15 a 10 终点 D 路径 b 2 b c 6 4 e 9 10
7 4
5
g
d
f 4
d e f g
c
15 ab
2 ac
10 ad
9 ace
16 14 6 acf acfg adg
Dijkstra算法讨论
1、算法的总的时间复杂度:O(n2) 2、权值要为正数,否则,得不到正确结果 3、当权值出现负数时,要使用BellmanFlord算法
// 对v的尚未访问的邻接顶点w递归调用DFS-T
Push(S, v);//顶点v的DFS函数执行完毕 } // DFS-T
拓扑排序---练习
写出下图的所有的拓扑序列
c
a
g
d e
f h
b
单源点的最短路径
给定带权有向图G和V0,求从V0到其余各 顶点的最短路径。 V5 V0
10
30 10
V4
Hale Waihona Puke 20V1AOV网(Activity On Vertex NetWork)
用顶点表示活动,弧表示活动间的优先关系的 有向图。 AOV网中不应该出现有向环:如果存在环,则某 项活动以自己为先决条件,
拓扑排序
B A C
可求得拓扑有序序列:
D
ABCD
或 ACBD
拓扑排序
B A D
C
不能求得它的拓扑有序序列。 因为图中存在一个回路 {B, C, D}
V3
V2
Dijkstra算法
1、按照路径长度递增的次序产生最短路径
v1 源点
v2

将最短路径的终点命名为V1,次之的终点命 名为V2,……
Dijkstra算法
2、用集合S记录下已经求出的顶点
S={V0}
S={V0, V1} S={V0, V1, V2}
…….
Dijkstra算法
3、用数组D记录V0到S中每个顶点的最短路径 的长度 S={V0,V1,V2,…,Vm} D[i]是V0到Vi的长度 0<= i <=m
Floyd 算法
首先对顶点进行编号,n个顶点对应1……n个整 数,分别叫做V1,V2,……,Vn 显然,顶点vi和vj之间的最短路径通过了n个 顶点的某些顶点。
Floyd 算法
Dijkstra算法
初始: 如果V与顶点V0邻接,则p[v][V0]=TRUE,其 它数矩阵元素的值都是FALSE。 当从V0到V的路径是经过V0到W的路径,然后, 通过边<W, V>到达V,则p[v] =p[w], p[v][v]=TRUE
Dijkstra算法
V5 V0
10
30 10
V0 V1 F F F F F F V2 F F T T F F F V 3 V4 V 5 F F F T F F F F F F F T F F F F F F T
•偏序就是集合中的部分成员可以比较。 •全序是集合中的任何成员之间都可以比较。 B A C 偏序 D A C 全序 B D
拓扑排序
按照有向图给出的次序关系,将图中顶点排成 一个线性序列,对于有向图中没有限定次序关系 的顶点,则可以人为加上任意的次序关系。
由此所得顶点的线性序列称之为拓扑有序序 列
拓扑排序
…………
}
Dijkstra算法实现
void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortestPathTable &D){ //主循环,每次求得v0到某个顶点v的最短路径, //并将v加到S集中 for(i=1;i<G.vexnum;++i){ min=INFINITY;//找余下顶点中的最短路径 for(w=0;w<G.vexnum;++w){ if(!final[w]) if(D[w]<min) {v=w; min=D[w]; } final[v]=TRUE;//v入选,即v0到v的路径最短
Dijkstra算法
如何找到Vk?
min( D[i] + dur(i,k)) i = 0,1,…k-1
Vk
S
Dijkstra算法
V5
V0
10
30 10
V4
20
V1 V2
V3
S={V0} D[0]=0
S={V0,V2} D[1]=10
S={V0,V2,V4,V3} D[3] = 50 S={V0,V2,V4,V3,V5}
Dijkstra算法实现
void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortestPathTable &D){ for(v=0;v<G.vexnum;++v){ final[v]=FALSE; //S中的顶点 D[v]=G.arcs[v0][v];//v0到v的路径的长度 for(w=0;w<G.vexnum;++w) p[v][w]=FALSE; if(D[v]<INFINITY){//V0的邻接点 p[v][v0]=TRUE; p[v][v]=TRUE; }//if }//for final[v0]=TRUE;
相关主题