/*
名称:求最短路径
说明:本实验包括
1.利用广度优先遍历统计单源最短路径
2.迪杰斯特拉算法求解有向图的单源最短路径
3.弗洛伊德算法求解所有顶点之间的最短路径
*/
#include<iostream>
#include "graph.h"
using namespace std;
访问标志数组(用作标记当前结点是否已访问)
bool visited2[MaxVertexNum];
//利用广度优先遍历统计单源最短路径
int * BFS_MIN_Distance(MGraph G,int u)
{
int *d = new int[G.vexnum]; //顶点u到其他顶点的距离向量
int val = -1;
//距离向量一开始初始化不可达
for(int i = 0;i<G.vexnum;++i)
{
d[i] = MaxDis;
}
d[u] = 0; //u到自己的距离为0
queue<int> Q;
Q.push(u);
visited2[u] = true; //标记已访问
while(Q.empty() == false)
{
val = Q.front(); //访问队首元素
Q.pop();
for(int w = FirstNeighbor1(G,val); w >= 0;w = NextNeighbor1(G,val,w))
{
if(visited2[w] == false)
{
Q.push(w);
visited2[w] = true;
d[w]= d[val]+1; //距离加一
}
}
}
return d;
}
//迪杰斯特拉算法求解有向图的单源最短路径
void Dijks_MIN_Distance(MGraph G,int v0)
{
int S[G.vexnum]; //用来记录已求得的最短路径的结点
int path[G.vexnum]; //用来记录从源点v0到其他各顶点i之间的最短路径的前驱结点
path[v0] = -1; //v0的前驱结点是-1
//int last_min_dis_vex = v0; //用来记录前驱结点
int dist[G.vexnum]; //记录从源点v0到其他各顶点的当前最短路径
//初始化
for(int i = 0;i<G.vexnum;++i)
{
S[i] = 0; //S集合初始化为零
dist[i] = G.Edge[v0][i]; //dist集合初始化为最开始的距离
}
for(int i = 0;i<G.vexnum-1;++i)
{
int temp_min = MaxDis;
int temp_vj = 0;
//从顶点集合V-S中选择最短的路径
for(int j = 0; j < G.vexnum;++j)
{
if(S[j] != 1 && dist[j] < temp_min)
{
temp_vj = j; //选择确定的结点
temp_min = dist[j]; //对应的最短距离
}
}
S[temp_vj] = 1; //将temp_vj加入集合
// path[temp_vj] = last_min_dis_vex; //上一个前驱结点
// last_min_dis_vex = temp_vj; //作为下一个选择的结点的前驱结点
//修改源点到每个顶点在选择的temp_vj为中介的情况下的最短路径
for(int k = 0;k<G.vexnum;++k)
{
if(S[k] == 0)
{
if(dist[temp_vj] + G.Edge[temp_vj][k] <= dist[k])
{
dist[k] = dist[temp_vj] + G.Edge[temp_vj][k]; //修改最短路径
path[k] = temp_vj;
}
}
}
}
//输出最短路径
cout<<"output the shortest path:"<<endl;
for(int i = 0;i<G.vexnum;++i)
{
cout<<dist[i]<<" ";
}
cout<<"\n";
//输出每个顶点最短路径的前驱
cout<<"output the precursor of every vertex:"<<endl;
for(int i = 0;i<G.vexnum;++i)
{
if(path[i] < 0)
cout<<GetVex1(G,i)<<"<--> "<<"源点"<<"\n";
else
cout<<GetVex1(G,i)<<"<--"<<GetVex1(G,path[i])<<"\n";
}
}
//弗洛伊德算法求解所有顶点之间的最短路径
void Floyd_MIN_Dis(MGraph G)
{
int temp_mis_dis[G.vexnum][G.vexnum]; //用来保存各顶点之间最短路径的矩阵
//初始化原始数据
for(int i = 0;i<G.vexnum;++i)
{
for(int j = 0;j<G.vexnum;++j)
{
temp_mis_dis[i][j] = G.Edge[i][j];
}
}
//弗洛伊德算法(三层循环)
for(int i = 0;i<G.vexnum;++i)
{
for(int j = 0;j<G.vexnum;++j)
{
for(int k = 0;k<G.vexnum;++k)
{
if(temp_mis_dis[j][k] > temp_mis_dis[j][i] + temp_mis_dis[i][k])
{
temp_mis_dis[j][k] = temp_mis_dis[j][i] + temp_mis_dis[i][k];
}
}
}
}
//输出结果矩阵
cout<<"output the result:"<<endl;
for(int i = 0;i<G.vexnum;++i)
{
for(int j = 0;j<G.vexnum;++j)
{
cout<<temp_mis_dis[i][j]<<" ";
}
cout<<endl;
}
}