图的应用:最短路径
思维导图:
最短路径的定义:
BFS算法:(无权单源最短路径)
void BFS_Distance(Graph G,int v){
for(int i=0;i<G.vexnum;++i)
d[i] = MAX;
visited[v] = true;
d[v] = 0;
EnQueue(Q,v);
while(!isEmpty(Q)){ //不空还有未遍历到的节点
DeQueue(Q,v); //出队v
for(w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) //找到所有符合条件的邻接节点
if(!visited[w]){ //w是否被访问
visited[w] = true; //修改该顶点对应数组的值为true
d[w] = d[v] + 1;
EnQueue(Q,w); //入队
}
}
}
Dijkstra算法:(无权单源、带权单源)
后续补充:至原理之前
Dijkstra算法原理:
注: 此算法只解决单源问题,即从一个确定顶点到其他所有顶点的路径问题
ps:
1、先初始化一个空结果集
2、让某一节点进入结果集
3、从非结果集中的顶点中选出一条最小权重的边,并将该边的另一个顶点加入结果集
4、从结果集的顶点出发到新加入的顶点的路径不止一条,要从多条路径中选出最短的一条,并修改对应数组值
5、重复3、4操作直到所有的顶点都加入到结果集中
要是实在看不懂,下面有具体实例讲解
算法实现中的辅助数组:
算法实现中用到的辅助数组:
1、s[]数组:标记已经加入了结果集的顶点
2、dist[]数组:从一个v0(某一个确定的节点)出发到各个节点的最短路径,若有多条路径选择最短的一条记录
3、path[]数组:记录到达该节点的前驱节点的数组下标,A->B->C,到达C的前驱节点为B
例:
这是重点,帮助理解;这是重点,帮助理解
后续的思路与上述相同,就不再赘述。
如何通过path[]数组找到0到其他顶点的路径?
ps:
因为path[4] = 2,即4的前驱是2
又path[2] = 0,即2的前驱又是0
又path[0] = -1,即0就是序列头节点
所有得到了序列0—>2—>4
其他原理类似,不在赘述
Dijkstra算法的代码实现:
void Dijkstra(Graph G,int v){ //图和源点
//初始化三个数组
int s[G.vexnum];
int path[G.vexnum];
int dist[G.vexnum];
for(int i=0;i<G.vexnum;i++){
dist[i] = G.edge[v][i];
s[i] = 0;
if(G.edge[v][i] < MAX)
path[i] = v;
else
path[i] = -1;
}
s[v] = 1;
path[v] = -1;
//寻找dist[]数组最小值
for(i=0;i<G.vexnum;i++){
int min = MAX;
int u;
for(int j=0;j<G.vexnum;j++)
if(s[j]==0 && dist[j]<min){
min = dist[j];
u = j;
}
s[u] = 1; //将u加入结果集
//加入了新的节点,更新数组
for(int j=0;j<G.vexnum;j++)
if(s[j]==0 && dist[u]+G.Edge[u][j] < dist[j]){
dist[j] = dist[u]+G.Edge[u][j];
path[j] = u;
}
}
}
Dijkstra算法适用范围及性能:
时间复杂度:O(|V|2)
存在负权值的图无法用Dijkstra算法
Floyd算法:
后期补充:至算法原理之前
Floyd算法原理:(动态规划)
A(0)矩阵表示加入0节点后的矩阵
A(1)矩阵表示加入节点1后的矩阵
ps:
在原来的结果集中加入一个节点k
节点i到节点k原有路径 与 经过k的路径比较
选最短的一条
例:
Floyd算法的代码实现:
void Floyd(Graph G){
int A[G.vexnum][G.vexnum];
//初始化
for(int i=0;i<G.vexnum;i++)
for(intj=0;j<G.vexnum;j++)
A[i][j] = G.Edge[i][j];
//对每一个值进行修改
for(int k=0;k<G.vexnum;k++) //考虑以Vk作为中转点
//修改某个值
for(int i=0;i<G.vexnum;i++) //遍历矩阵i为行号,j为列号
for(intj=0;j<G.vexnum;j++)
if(A[i][j] > A[i][k] + a[k][j]) //判断路径是否最优
A[i][j] = A[i][k] + a[k][j]; //更新最短路径长度
//path[i][j] = k;
}
性能分析:
时间复杂度:O(|V|^3)
空间复杂度:O(|V|^2)