赞
踩
- 初始化数组dist、path和s;
- while (s中的元素个数<n)
2.1 在dist[n]中求最小值,其下标为k;
2.2 输出dist[j]和path[j];
2.3 修改数组dist和path;
2.4 将顶点vk添加到数组s中;
const int MaxSize=100;
const int MAX=10000;//最大距离
struct Path
{
string route[MaxSize];//一点到所有点的最短路径
int t;//t是route[]数组所用的下标,代表一条路径中的第t个点
};
template<class DataType>
class MGraph
{
public:
MGraph();
~MGraph(){}
void DFSTraverse(int v);
void BFSTraverse(int v);
void Dijkstra(int v);
void Floyd();
void PrintfGraphAL();
int vertexNum,arcNum;//图的顶点数和边数
double dist[MaxSize];//一点到所有点的最短距离
double Dist[MaxSize][MaxSize];//任意两点之间的最短距离
Path path[MaxSize];//一点到所有点的最短路径
DataType vertex[MaxSize];//顶点
private:
int arc[MaxSize][MaxSize];//图的边长
bool DFSvisited[MaxSize];//定义一个DFS遍历过标记
bool BFSvisited[MaxSize];//定义一个BFS遍历过标记
};
template<class DataType>//构造函数
MGraph<DataType>::MGraph()
{
int i,j;
fstream fcin_vertex;
fcin_vertex.open("vertex.txt",ios::in);//打开一个文件用于从文件输入顶点
vertexNum=0,arcNum=0;//令顶点数、边数赋值为0
while(!fcin_vertex.eof())
fcin_vertex>>vertex[vertexNum++];
fcin_vertex.close();
memset(DFSvisited,0,sizeof(DFSvisited));//这个函数用来给DFSvisited数组所有成员赋0
memset(BFSvisited,0,sizeof(BFSvisited));
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
{
if(i==j)
arc[i][j]=0;//如果是相同顶点,则初始化为0
else
arc[i][j]=MAX;//否则将边长初始化为MAX;
}
fstream fcin_arc;
fcin_arc.open("arc.txt",ios::in);//打开一个文件用于从文件输入边
i=0,j=0;
while(i!=-1)
{
fcin_arc>>i;
if(i==-1)
continue;
else
{
fcin_arc>>j;
if(arc[i][j]==0||arc[i][j]==MAX)//如果这条边等于0或者等于MAX,说明这条边还没被修改过,这时候修改一次,边数+1,
//否则,则说明这条边已经被修改过,再修改边数也不会增加
arcNum++;
fcin_arc>>arc[i][j];
arc[j][i]=arc[i][j];//由于是无向图,i到j的距离等于j到i的距离
}
}
fcin_arc.close();
}
/*迪杰斯特拉算法
1.初始化path数组,dist数组,集合S,把起点v加入path数组,并把所有的从起点v一步能够到达的点加入path数组,把起点的遍历标记S置1
2.执行n-1步循环
2.1在dist数组中找到最小值dist[j],这个值即为v到j的最小距离,把这个dist值以及对应的path路径输出
2.2以2.1中path的终点k为新的起点,遍历所有的点,找到所有从新的起点k出发到达j(dist[k]+arc[k][j])
比原来的起点出发到达j(dist[j])的距离更短的点j,并把dist值修改为dist[k]+arc[k][j],将path[k]赋给path[j],并将新的点j放入path[j]中
*/
template<class DataType>//迪杰斯特拉算法(求一个点到所有点的最短路径算法)这里设那“一个点”为v点
void MGraph<DataType>::Dijkstra(int v)
{
int i,j,num,b;
bool S[MaxSize];//这是一个点是否被加入到集合S中的标记
for(i=0;i<vertexNum;i++)//初始化dist[]、S[]、path[]数组
{
dist[i]=arc[v][i];//将要寻找的点到所有点的距离初始化,即按照邻接矩阵赋值
S[i]=0;//将所有点是否被加入到集合S中的标记置0,即尚未加入
path[i].t=0;//t是route[]数组所用的下标,代表一条路径中的第t个点,初始化为0
path[i].route[path[i].t]=vertex[v];//将要寻找的点到所有点的路径path[]初始化,即只有起点本身
if(dist[i]!=MAX)//如果将要寻找的点到任意一点i的距离不等于MAX,即起点到点i存在边
path[i].route[++path[i].t]=vertex[i];//就把点i加入路径path[i]中
}
S[v]=1;//开始遍历,将起点的遍历标记置1
for(num=1;num<vertexNum;num++)//循环vertexNum-1次,即有n个点,就得寻找n-1次,每次找出一个点
{
//下面的这个循环将会寻找出从当前起点出发,到达所有点的最小距离
double min=MAX;//记当前起点出发到所有点的距离为min{len<v,j>},初始化min{len<V,j>}=MAX
int k=v;//k为min{len<v,j>}最小的点,初始为起点
for(j=0;j<vertexNum;j++)//在dist[]中寻找最小值
if(S[j]==0&&dist[j]!=0&&dist[j]<=min)//如果有一个点j,满足:没有被加入到S[],并且到点v的距离不是0(不是v点本身),并且距离小于当前最小值
{
k=j;//保存j点的下标到k中
min=dist[j];//令当前的最小值为dist[k]
}
S[k]=1;//把k点放入S[]
for(j=0;j<vertexNum;j++)//现在的起点为k,再次遍历所有点寻找有没有点j 满足:从新的起点k出发(dist[k]+arc[k][j])
//到达j比原来的起点出发到达j的距离更短
if(S[j]==0&&arc[k][j]<MAX)//如果点j没有加入S[]并且k点到j点有边(距离不为MAX)
{
if(dist[j]>dist[k]+arc[k][j])//这步意图在 比较从之前的起点出发到达j(dist[j])和 从新的起点k出发到达j(dist[k]+arc[k][j])
//哪种方式距离更短,取更短的那种
{
dist[j]=dist[k]+arc[k][j];//如果从k更短,就把更短的距离赋给dist[j]
for(b=0;b<=path[k].t;b++)//把path[k].route复制给path[j].route
path[j].route[b]=path[k].route[b];
path[j].t=path[k].t;
path[j].route[++path[j].t]=vertex[j];//将点j加入path[j].route
}
}
}
}
template<class DataType>//Floyd算法(求任意一点到任意一点的最短路径算法)
void MGraph<DataType>::Floyd()
{
int i,j,k;
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
Dist[i][j]=arc[i][j];//将任意两点之间的距离初始化,即按照邻接矩阵赋值
//下面相当于运用了vertexNum次Dijkstra算法
for(k=0;k<vertexNum;k++)
//下面的双重循环将用来找出所有 满足:i经过k到达j的距离<i按照之前路径到达j的距离 这一条件的点
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
if(Dist[i][k]+Dist[k][j]<Dist[i][j])//如果i经过k到达j的距离<i直接到达j的距离
Dist[i][j]=Dist[i][k]+Dist[k][j];//把i到j的距离改为如果i经过k到达j的距离
}
#include<iostream>
using namespace std;
#include<conio.h>//getch()函数头文件
#include<string>//新版vc的getch()函数头文件
#include<stdlib.h>//调节颜色头文件
#include<fstream>
const int MaxSize=100;
const int MAX=10000;//最大距离
struct Path
{
string route[MaxSize];//一点到所有点的最短路径
int t;//t是route[]数组所用的下标,代表一条路径中的第t个点
};
template<class DataType>
class MGraph
{
public:
MGraph();
~MGraph(){}
void DFSTraverse(int v);
void BFSTraverse(int v);
void Dijkstra(int v);
void Floyd();
void PrintfGraphAL();
int vertexNum,arcNum;//图的顶点数和边数
double dist[MaxSize];//一点到所有点的最短距离
double Dist[MaxSize][MaxSize];//任意两点之间的最短距离
Path path[MaxSize];//一点到所有点的最短路径
DataType vertex[MaxSize];//顶点
private:
int arc[MaxSize][MaxSize];//图的边长
bool DFSvisited[MaxSize];//定义一个DFS遍历过标记
bool BFSvisited[MaxSize];//定义一个BFS遍历过标记
};
template<class DataType>//构造函数
MGraph<DataType>::MGraph()
{
int i,j;
fstream fcin_vertex;
fcin_vertex.open("vertex.txt",ios::in);//打开一个文件用于从文件输入顶点
vertexNum=0,arcNum=0;//令顶点数、边数赋值为0
while(!fcin_vertex.eof())
fcin_vertex>>vertex[vertexNum++];
fcin_vertex.close();
memset(DFSvisited,0,sizeof(DFSvisited));//这个函数用来给DFSvisited数组所有成员赋0
memset(BFSvisited,0,sizeof(BFSvisited));
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
{
if(i==j)
arc[i][j]=0;//如果是相同顶点,则初始化为0
else
arc[i][j]=MAX;//否则将边长初始化为MAX;
}
fstream fcin_arc;
fcin_arc.open("arc.txt",ios::in);//打开一个文件用于从文件输入边
i=0,j=0;
while(i!=-1)
{
fcin_arc>>i;
if(i==-1)
continue;
else
{
fcin_arc>>j;
if(arc[i][j]==0||arc[i][j]==MAX)//如果这条边等于0或者等于MAX,说明这条边还没被修改过,这时候修改一次,边数+1,
//否则,则说明这条边已经被修改过,再修改边数也不会增加
arcNum++;
fcin_arc>>arc[i][j];
arc[j][i]=arc[i][j];//由于是无向图,i到j的距离等于j到i的距离
}
}
fcin_arc.close();
}
template<class DataType>
void MGraph<DataType>::DFSTraverse(int v)
{
int j;
cout<<vertex[v]<<" ";//遍历到该点,即输出
DFSvisited[v]=1;//然后将该点的遍历标记置1
for(j=0;j<vertexNum;j++)
if(arc[v][j]!=0&&arc[v][j]!=MAX&&DFSvisited[j]==0)//如果边不等于0并且不等于MAX并且该点没有遍历过,就深度优先遍历
DFSTraverse(j);
}
template<class DataType>//广度优先遍历
void MGraph<DataType>::BFSTraverse(int v)
{
int Q[MaxSize];
int front=-1,rear=-1,j;
cout<<vertex[v]<<" ";//先输出开始广度遍历的结点
BFSvisited[v]=1;//并把刚才输出的结点标记为1
Q[++rear]=v;//将该结点入队
while(front!=rear)//如果队非空
{
v=Q[++front];//把队头结点出队,并将出队的结点的数组下标赋给v
for(j=0;j<vertexNum;j++)//for循环寻找下一个满足 边不等于0并且不等于MAX并且该点没有遍历过 的结点
if(arc[v][j]!=0&&arc[v][j]!=MAX&&BFSvisited[j]==0)//如果边不等于0并且不等于MAX并且该点没有遍历过
{
cout<<vertex[j]<<" ";//输出找到的结点
BFSvisited[j]=1;//标记置1
Q[++rear]=j;//结点入队
}
}
}
/*迪杰斯特拉算法
1.初始化path数组,dist数组,集合S,把起点v加入path数组,并把所有的从起点v一步能够到达的点加入path数组,把起点的遍历标记S置1
2.执行n-1步循环
2.1在dist数组中找到最小值dist[j],这个值即为v到j的最小距离,把这个dist值以及对应的path路径输出
2.2以2.1中path的终点k为新的起点,遍历所有的点,找到所有从新的起点k出发到达j(dist[k]+arc[k][j])
比原来的起点出发到达j(dist[j])的距离更短的点j,并把dist值修改为dist[k]+arc[k][j],将path[k]赋给path[j],并将新的点j放入path[j]中
*/
template<class DataType>//迪杰斯特拉算法(求一个点到所有点的最短路径算法)这里设那“一个点”为v点
void MGraph<DataType>::Dijkstra(int v)
{
int i,j,num,b;
bool S[MaxSize];//这是一个点是否被加入到集合S中的标记
for(i=0;i<vertexNum;i++)//初始化dist[]、S[]、path[]数组
{
dist[i]=arc[v][i];//将要寻找的点到所有点的距离初始化,即按照邻接矩阵赋值
S[i]=0;//将所有点是否被加入到集合S中的标记置0,即尚未加入
path[i].t=0;//t是route[]数组所用的下标,代表一条路径中的第t个点,初始化为0
path[i].route[path[i].t]=vertex[v];//将要寻找的点到所有点的路径path[]初始化,即只有起点本身
if(dist[i]!=MAX)//如果将要寻找的点到任意一点i的距离不等于MAX,即起点到点i存在边
path[i].route[++path[i].t]=vertex[i];//就把点i加入路径path[i]中
}
S[v]=1;//开始遍历,将起点的遍历标记置1
for(num=1;num<vertexNum;num++)//循环vertexNum-1次,即有n个点,就得寻找n-1次,每次找出一个点
{
//下面的这个循环将会寻找出从当前起点出发,到达所有点的最小距离
double min=MAX;//记当前起点出发到所有点的距离为min{len<v,j>},初始化min{len<V,j>}=MAX
int k=v;//k为min{len<v,j>}最小的点,初始为起点
for(j=0;j<vertexNum;j++)//在dist[]中寻找最小值
if(S[j]==0&&dist[j]!=0&&dist[j]<=min)//如果有一个点j,满足:没有被加入到S[],并且到点v的距离不是0(不是v点本身),并且距离小于当前最小值
{
k=j;//保存j点的下标到k中
min=dist[j];//令当前的最小值为dist[k]
}
S[k]=1;//把k点放入S[]
/*if(dist[k]<MAX)
{
cout<<v<<vertex[v]<<"到"<<k<<vertex[k]<<"的最短路径为:"<<endl;
for(j=0;j<path[k].t;j++)
cout<<path[k].route[j]<<"->";
cout<<path[k].route[j];
cout<<"\t最小距离为"<<dist[k]<<endl;//输出起点v到点k的最短路径和最小距离
}
else
cout<<vertex[v]<<"不能到点"<<vertex[k]<<endl;*/
for(j=0;j<vertexNum;j++)//现在的起点为k,再次遍历所有点寻找有没有点j 满足:从新的起点k出发(dist[k]+arc[k][j])
//到达j比原来的起点出发到达j的距离更短
if(S[j]==0&&arc[k][j]<MAX)//如果点j没有加入S[]并且k点到j点有边(距离不为MAX)
{
if(dist[j]>dist[k]+arc[k][j])//这步意图在 比较从之前的起点出发到达j(dist[j])和 从新的起点k出发到达j(dist[k]+arc[k][j])
//哪种方式距离更短,取更短的那种
{
dist[j]=dist[k]+arc[k][j];//如果从k更短,就把更短的距离赋给dist[j]
for(b=0;b<=path[k].t;b++)//把path[k].route复制给path[j].route
path[j].route[b]=path[k].route[b];
path[j].t=path[k].t;
path[j].route[++path[j].t]=vertex[j];//将点j加入path[j].route
}
}
}
}
template<class DataType>//Floyd算法(求任意一点到任意一点的最短路径算法)
void MGraph<DataType>::Floyd()
{
int i,j,k;
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
Dist[i][j]=arc[i][j];//将任意两点之间的距离初始化,即按照邻接矩阵赋值
//下面相当于运用了vertexNum次Dijkstra算法
for(k=0;k<vertexNum;k++)
//下面的双重循环将用来找出所有 满足:i经过k到达j的距离<i按照之前路径到达j的距离 这一条件的点
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
if(Dist[i][k]+Dist[k][j]<Dist[i][j])//如果i经过k到达j的距离<i直接到达j的距离
Dist[i][j]=Dist[i][k]+Dist[k][j];//把i到j的距离改为如果i经过k到达j的距离
}
int main()
{
MGraph<string> graph;//构造图
char N;
int i,j;
system("color 0A");
while(true)
{
cout<<"请输入需要的功能N:"<<endl;
cout<<"0.退出\n";
cout<<"1.统计图中边数\n";
cout<<"2.深度优先遍历\n";
cout<<"3.广度优先遍历\n";
cout<<"4.求一地点到所有地点的距离\n";
cout<<"5.求一地点到另一地点的距离\n";
cin>>N;
if(N=='0')break;
switch(N)
{
case '1':
cout<<"图的边数为:"<<graph.arcNum<<endl;
cout<<"--请按任意键继续--\n";
_getch();
system("CLS");
break;
case '2':
cout<<"图的深度优先遍历结果为:";
graph.DFSTraverse(0);
cout<<endl;
cout<<"--请按任意键继续--\n";
_getch();
system("CLS");
break;
case '3':
cout<<"图的广度优先遍历结果为:";
graph.BFSTraverse(0);
cout<<endl;
cout<<"--请按任意键继续--\n";
_getch();
system("CLS");
break;
case '4':
int v;
cout<<"请输入求哪个(0~15)点到其他点的最小距离:";
cin>>v;
graph.Dijkstra(v);
for(i=0;i<graph.vertexNum;i++)
{
if(i!=v)
{
cout<<v<<graph.vertex[v]<<"到"<<i<<graph.vertex[i]<<"的最短路径为:"<<endl;
for(j=0;j<graph.path[i].t;j++)
cout<<graph.path[i].route[j]<<"->";
cout<<graph.path[i].route[j];
cout<<"\t最小距离为"<<graph.dist[i]<<endl;//输出起点v到点k的最短路径和最小距离
}
}
cout<<"--请按任意键继续--\n";
_getch();
system("CLS");
break;
case '5':
int i1,i2;
graph.Floyd();
cout<<"请输入第一个点(0~15):";
cin>>i1;
cout<<"请输入第二个点(0~15):";
cin>>i2;
graph.Dijkstra(i1);
cout<<i1<<graph.vertex[i1]<<"到"<<i2<<graph.vertex[i2]<<"的最短路径为:"<<endl;
for(j=0;j<graph.path[i2].t;j++)
cout<<graph.path[i2].route[j]<<"->";
cout<<graph.path[i2].route[j];
cout<<"最小距离是:"<<graph.Dist[i1][i2]<<endl;
cout<<"--请按任意键继续--\n";
_getch();
system("CLS");
break;
default:
cout<<"输入错误,请重新输入!\n";
cout<<"--请按任意键继续--\n";
_getch();
system("CLS");
}
}
return 0;
}
西街 公寓楼 鸿远楼 修远楼 明远楼 逸夫图书馆 行政楼 南门 树慧园 天行健 澡堂 北门 操场 仙女楼
校医院 东门
0 1 50
0 2 80
1 2 100
1 3 200
2 4 200
3 4 100
3 5 150
4 5 70
4 6 70
5 6 100
5 8 300
6 7 50
8 9 100
8 10 70
8 13 50
9 10 70
10 12 50
10 13 150
12 11 150
12 13 50
13 14 300
13 15 100
-1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。