数据结构实验报告 最短路径
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告实验名称最短路径
课程名称数据结构与算法实验
|
|
专业班级:信息安全
学号:
姓名:
实验六最短路径
一、实验目的
1.学习掌握图的存储结构
2.学会编写求最短路径的算法
二、实验内容
1、实验题目
编写代码实现Dijkstra生成最短路径的算法,其中要有完整的图的输入输出
2、简单介绍
图的存储:用邻接矩阵,这样会方便不少。
邻接矩阵是一个二维数组,数组中的元素是边的权(一些数值),数组下标号为结点的标号。
(1)例如二维数组中的一个元素M[5][6]的值为39,则表示结点5、6连接,且其上的权值为39。
(2)用邻接矩阵存储图,对图的读写就简单了。
因为邻接矩阵就是一个二维数组,因此对图的读写就是对二维数组的操作。
只要能弄清楚边的编号,就能把图读入了。
用一对结点表示边(也就是输入的时候输入一对结点的编号)
求最短路径的算法:
求最短路径就是求图中的每一个点到图中某一个给定点(这里认为是编号为0的点)的最短距离。
具体算法就是初始有一个旧图,一个新图。
开始的时候旧图中有所有的结点,新图中初始为只有一个结点(源点,路径的源头)。
整个算法就是不停的从旧图中往新图中添加点,直到所有的点都添加到新图中为止。
要实现这个算法,除了用二维数组保存图,还需要使用到两个辅助的数组
数组find[N]:此数组是用来表示标号对应的结点是否已经被添加到新图中(因为只有旧图中的点我们才需要添加到新图中,并且只有旧图中点到源点的距离,我们才需要进行更新)其中N为图中结点的个数。
数组distance[N]:此数组记录图中的点到源点的距离。
这个数组里面存放的值是不断进行更新的。
其中N为图中结点的个数。
3、程序简单模板
只是参考,不需要照着这个来写
//最短路径
#ifndef MYGRAPH_H_
#define MYGRAPH_H_
class MyGraph
{
public:
void readDirectedGraph();
MyGraph(int size);//构造函数中设置图的大小,分配空间void writeGraph();
void shortPath(int source);//求最短路径
protected:
private:
int **m_graph;//用二维数组保存图
int m_size;//图的大小
};
#endif
///////////////////////////////////////////// ////////////////////////
//构造函数中设置图的大小,分配空间
MyGraph::MyGraph(int size)
{
int i,j;
m_size=size;
//给图分配空间
m_graph=new int* [m_size];
for (i=0;i<m_size;i++)
{
m_graph[i]=new int[m_size];
}
for (i=0;i<m_size;i++)
{
for(j=0;j<m_size;j++)
{
m_graph[i][j]=INT_MAX;
}
}
}
三、实验代码
#include<iostream>
#include <iomanip>
#include <stack>
#include <deque>
#include <fstream>
using namespace std;
struct primnode
{
public:
char begvex;
char endvex;
int lowcost;
};
struct adknode
{
int dist;//最近距离
char way[50];//顶点数组
int nodenum;//经过的顶点数
};
class Mgraph//邻接矩阵储存结构
{
public:
Mgraph(){}
~Mgraph(){}
void CreatMGraph();
void DFS (int );//用递归实现
void DFS1(int );//非递归
void BFS(int );
void print();
void prim();
int mini();
int low();//最短距离函数的辅助函数
int LocateVex(char);
void kruskal();
void Dijkstra();
void Floyd();
private:
int number;//顶点数目
int arcnum;//边的数目
char vexs[50];
int arcs[50][50];
int visited[50];//便利时的辅助工具
primnode closeedge[50];//prim
adknode dist[50];//最短路径
int D[20][20];//floyd算法距离
int P[20][20][20];//floyd算法路径
};
int Mgraph::LocateVex(char s)
{
for(int i=0;i<number;i++)
if (vexs[i]==s)
return i;
return -1;
}
void Mgraph::print()
{
cout<<"顶点为:";
for(int k=0;k<number;k++)
cout<<vexs[k];
cout<<endl;
for(int i=0;i<number;i++)
{
for(int j=0;j<number;j++)
cout<<setw(6)<<left<<arcs[i][j]<<" ";
cout<<endl;
}
for(int m=0;m<number;m++)
cout<<visited[m];
cout<<endl;
}
void Mgraph::CreatMGraph()//图的邻接矩阵储存结构{
char vex1,vex2;
int i,j,k,m;
cout<<"请输入定点数,边数:"<<endl;
cin>>number>>arcnum;
cout<<"请输入顶点(字符串类型):"<<endl;
for(i=0;i<number;i++)
cin>>vexs[i];
for(i=0;i<number;i++)
for(j=0;j<number;j++)
arcs[i][j]=1000;
for(k=0;k<arcnum;k++)
{
cout<<"请输入边的两个顶点及边的权值:"<<endl; cin>>vex1>>vex2>>m;
i=LocateVex(vex1);
j=LocateVex(vex2);
arcs[i][j]=m;
arcs[j][i]=m;
}
}
void Mgraph::DFS(int i=0)//用递归实现
{
int j;
cout<<vexs[i]<<"------>";
visited[i]=1;
for (j=0;j<number;j++)
{
if(!(arcs[i][j]==1000)&&!visited[j])
DFS(j);
}
}
void Mgraph::DFS1(int i=0)//非递归
{
stack<int> st;
st.push(i);
while(!st.empty())
{
int j=st.top();
st.pop();
cout<<vexs[j]<<"---->";
visited[j]=1;
for(int k=0;k<number;k++)
{
if((!(arcs[j][k]==1000))&&!visited[k])
st.push(k);
}
}
}
void Mgraph::BFS(int i=0)//广度优先遍历
{
deque<int> de;
de.push_back(i);
cout<<vexs[i]<<"------>";
visited[i]=1;
while(!de.empty())
{
int k=de.front();
for(int j=0;j<number;j++)
{
if(arcs[k][j]!=1000&&!visited[j])
{
cout<<vexs[j]<<"------>";
visited[j]=1;
de.push_back(j);
}
}
de.pop_front();
}
}
int Mgraph::mini()
{
static int i;
int min=0;
for (int j=0;j<number;j++)
{
if(!visited[j])
{
if (closeedge[min].lowcost>closeedge[j].lowcost)
{
min=j;
}
}
}
i=min;
cout<<"包括边("<<closeedge[i].begvex<<","<<closeedge[i].endvex<<")"; return i;
}
void Mgraph::prim()
{
char u;
cout<<"请输入起始顶点:"<<endl;
cin>>u;
int i=LocateVex(u);
visited[i]=1;
for(int j=0;j<number;j++)
{
closeedge[j].begvex=u;
closeedge[j].endvex=vexs[j]; closeedge[j].lowcost=arcs[i][j];
}
for (int m=1;m<number;m++)
{
int n=mini();
visited[n]=1;
closeedge[n].lowcost=1000;
for (int p=0;p<number;p++)
{
if(!visited[p])
{
if(arcs[p][n]<closeedge[p].lowcost)
{
closeedge[p].lowcost=arcs[p][n];
closeedge[p].begvex=vexs[n];
}
}
}
}
}
void Mgraph::kruskal()
{
int a,b,k=0;
int min=1000;
int arcs1[20][20];
for (int m=0;m<number;m++)
visited[m]=m;//每一个顶点属于一颗树for (int i=0;i<number;i++)
for(int j=0;j<number;j++)
arcs1[i][j]=arcs[i][j];
while (k<number-1)
{
min=1000;
for (int i=0;i<number;i++)
{
for (int j=0;j<number;j++)
{
if (arcs1[i][j]<min)
{
a=i;
b=j;
min=arcs1[i][j];
}
}
}
if (visited[a]!=visited[b])
{
cout<<"包括边("<<vexs[a]<<","<<vexs[b]<<")";
k++;
for (int n=0;n<number;n++)
{
if (visited[n]==visited[b])
visited[n]=visited[a];
}
}
else
arcs1[a][b]=arcs[b][a]=1000;
}
}
void Mgraph::Dijkstra()
{
cout<<"请输入起始点"<<endl;
char u;
cin>>u;
int i=LocateVex(u);
visited[i]=1;
for (int j=0;j<number;j++)
{
dist[j].dist=arcs[i][j];
dist[j].nodenum=0;
}
for (j=1;j<number;j++)
{
int distance=1000;
int min=0;
for (int n=0;n<number;n++)
{
if(!visited[n])
{
if (distance>dist[n].dist)
{
distance=dist[n].dist;
min=n;
}
}
}
int m=min;
visited[m]=1;
for (n=0;n<number;n++)
{
if(!visited[n])
{
if((dist[m].dist+arcs[m][n])<dist[n].dist)
{
dist[n].dist=dist[m].dist+arcs[m][n];
dist[n].nodenum=0;
for (int x=0;x<dist[m].nodenum;x++)
{
dist[n].way[x]=dist[m].way[x];
dist[n].nodenum++;
}
dist[n].way[dist[n].nodenum++]=vexs[m];
} } } }
//输出功能
for (int n=0;n<number;n++)
{
if (n!=i)
{ if(dist[n].dist<1000)
{
cout<<vexs[i]<<"到"<<vexs[n]<<"的最近距离为:"<<dist[n].dist<<endl;
cout<<"经过的顶点为:"<<vexs[i]<<"---->";
for (int p=0;p<dist[n].nodenum;p++)
{ cout<<dist[n].way[p]<<"----->";
}
cout<<vexs[n]<<endl;
}
else
cout<<vexs[i]<<"到"<<vexs[n]<<"没有通路"<<endl;
} } }
void Mgraph::Floyd()
{
int i,j,m,n;
for ( i=0;i<number;i++)
for ( j=0;j<number;j++)
for (m=0;m<number;m++)
P[i][j][m]=0;
for ( i=0;i<number;i++)
for ( j=0;j<number;j++)
{
D[i][j]=arcs[i][j];
if(D[i][j]<1000)
{
P[i][j][i]=1;
P[i][j][j]=1;
} }
for ( i=0;i<number;i++)
for ( j=0;j<number;j++)
for (m=0;m<number;m++)
{
if (i==j||j==m||i==m)
continue;
if (D[i][m]+D[m][j]<D[i][j])
{
D[i][j]=D[i][m]+D[m][j];
for (n=0;n<number;n++)
{
P[i][j][n]=P[i][m][n]||P[m][j][n];
} } }
for ( i=0;i<number;i++)
for ( j=0;j<number;j++)
{
if (D[i][j]<1000)
{
cout<<vexs[i]<<"到"<<vexs[j]<<"的最近距离为:"<<D[i][j]<<endl;
cout<<"经过的顶点为:";
for (m=0;m<number;m++)
{
if (P[i][j][m])
{
cout<<vexs[m]<<"------>";
} }
cout<<endl;}
else
if (i!=j)
cout<<vexs[i]<<"到"<<vexs[j]<<"没有通路"<<endl;
}
}
int main()
{
Mgraph g;
g.CreatMGraph();
g.Floyd();
return 0;
}
四、实验结果
五、实验总结
本次实验主要是学习掌握图的存储结构,学会编写求最短路径的算法。
本次实验的算法虽有点复杂,但是多上机练习,完成本次实验也不是难事。