实验性质:综合性实验
要求:
(1)采用邻接矩阵/邻接表建立图;
(2)采用深度优先/广度优先搜索方式遍历图;
(3)编程实现Dijkstra最短路径算法。
目的:
(1)掌握图的邻接矩阵和邻接表存储方式;
(2)掌握图的遍历算法;
(3)掌握图的实际应用——最短路径算法。
代码
#include <iostream>
using namespace std;
//***邻接矩阵***//
#define MaxInt 32767 //表示极大值,即∞
#define MVNum 100 //最大顶点数
bool visited[MVNum],visited2[MVNum]; //初始化标志数组,值为false
typedef int VertexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
typedef struct{
VertexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的顶点数和边数
}AMGraph;
//***邻接表***//
typedef struct ArcNode //边结点
{
int adjvex; //该边所指向的顶点的位置
struct ArcNode * nextarc; //指向下一条边的指针
int info; //和边相关的信息
}ArcNode;
typedef struct VNode //顶点信息
{
int data;
ArcNode * firstarc; //指向第一条依附该顶点的边的指针
}VNode,AdjList [MVNum]; //AdjList表示邻接表类型
typedef struct
{
AdjList vertices;
int vexnum,arcnum; //图的当前顶点数和边数
}ALGraph;
int LocateVex(ALGraph G,int u); //返回顶点u在图G中的位置
void CreateUDG(ALGraph &G);//邻接表建立无向图
void DFS_AL(ALGraph &G,int v);//邻接表表示图的深度优先搜索遍历
void CreateUDN(AMGraph &G2); //邻接矩阵法建立有向图
void DFS_AM(AMGraph &G2,int v); //邻接矩阵深度优先搜索遍历
void ShortestPath_DIJ(AMGraph G, int v0); //Dijkstra算法
void Menu(); //文字菜单提示信息
int main()
{
ALGraph G;
AMGraph G2;
Menu();
int v=0,v0=0;
int i; //输入的数字
cout<<"请输入操作代码:";
cin>>i;
while(true)
{
switch(i)
{
case 1:
CreateUDG(G);
break;
case 2:
DFS_AL(G,v);
cout<<endl;
break;
case 3:
CreateUDN(G2);
break;
case 4:
DFS_AM(G2,v);
cout<<endl;
break;
case 5:
ShortestPath_DIJ(G2,v0);
break;
default:
if(i<0)
return 0;
else
{
cout<<"输入的位置非法,请重新输入";
break;
}
}
cout<<"请输入操作代码:";
cin>>i;
}
return 0;
}
int LocateVex(ALGraph G,int u) //返回顶点u在图G中的位置
{
int i;
for (i = 0; i < G.vexnum; i++)
{
if (u == G.vertices[i].data)
return i;
}
return 0;
}
int LocateVex(AMGraph G2,int u) //返回顶点u在图G中的位置
{
for(int i=0; i<G2.vexnum; i++)
if(u==G2.vexs[i])
return i;
return 0;
}
void CreateUDG(ALGraph &G) //邻接表法
{
cout<<"输入总顶点数,总边数:";
cin>>G.vexnum>>G.arcnum; //总顶点数,总边数
cout<<"输入顶点值:";
for(int i=0;i<G.vexnum;i++) //输入各点,构造表头结点表
{
cin>>G.vertices[i].data; //输入顶点值
G.vertices[i].firstarc=NULL; //初始化表头结点的指针域为NULL
}
cout<<"输入每条边依附的两个顶点:"<<endl;
for(int k=0;k<G.arcnum;++k) //输入各边,构造邻接表
{
int v1,v2;
cin>>v1>>v2; //输入一条边依附的两个顶点
int i=LocateVex(G,v1); int j=LocateVex(G,v2);
//确定v1和v2在G中位置,即顶点在G.vertices中的序号
ArcNode *p1=new ArcNode; //生成一个新的边结点
p1->adjvex=j; //邻接点序号为j
p1->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
//将新节点*p1插入v1的边表头部
ArcNode *p2=new ArcNode; //生成另一个对称的新节点*p2
p2->adjvex=i; //邻接点序号为i
p2->nextarc=G.vertices[j].firstarc; G.vertices[j].firstarc=p2;
//将新节点p2插入顶点v1的边表头部
}
cout<<"创建成功"<<endl;
}
void DFS_AL(ALGraph &G,int v)
{//图G为邻接表类型,从第v个顶点出发深度优先搜索遍历图G
cout<<v;visited[v]=true; //访问第v个顶点,并置访问标志数组相应分量值为true
ArcNode *p=G.vertices[v].firstarc; //p指向v的第一个边结点
while(p!=NULL) //边结点非空
{
int w=p->adjvex; //表示w是v的邻接点
if(!visited[w])
DFS_AL(G,w); //如果w未访问,则递归调用DFS_AL
p=p->nextarc; //p指向下一个边结点
}
}
void CreateUDN(AMGraph &G2) //邻接矩阵法
{
//采用邻接矩阵表示法,创建无向网G
cout<<"输入总顶点数,总边数:";
cin>>G2.vexnum>>G2.arcnum; //输入总顶点数,总边数
cout<<"输入顶点值:";
for(int i = 0; i<G2.vexnum; ++i)
cin>>G2.vexs[i]; //依次输入顶点的信息
for(int i = 0; i<G2.vexnum;++i) //初始化邻接矩阵,边的权值均为极大值
for(int j = 0; j<G2.vexnum;++j)
G2.arcs[i][j] = MaxInt;
cout<<"输入每条边依附的顶点及权值:"<<endl;
for(int k = 0; k<G2.arcnum;++k)
{ //构造邻接矩阵
int v1,v2,w;
cin>>v1>>v2>>w; //输入一条边依附的顶点及权值
int i = LocateVex(G2, v1);
int j = LocateVex(G2, v2); //确定v1和v2在G中的位置
G2.arcs[i][j] = w; //边<v1, v2>的权值置为w2
//取消下面注释即建立无向图
//G2.arcs[j][i] = G2.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
}
cout<<"创建成功"<<endl;
}
void DFS_AM(AMGraph &G2, int v){ //图G2为邻接矩阵类型
cout<<v;
visited2[v] = true; //访问第v个顶点
for(int w = 0; w< G2.vexnum; w++) //依次检查邻接矩阵v所在的行
if((G2.arcs[v][w]!=MaxInt) && (!visited2[w]))
DFS_AM(G2, w);
//w是v的邻接点,如果w未访问,则递归调用DFS
}
void ShortestPath_DIJ(AMGraph G, int v0)
{
bool S[MVNum];int D[MVNum],Path[MVNum];
//用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径
int n=G.vexnum; //n为G中顶点的个数
for(int v = 0; v<n; ++v)
{ //n个顶点依次初始化
S[v] = false; //S初始为空集
D[v] = G.arcs[v0][v]; //将v0到各个终点的最短路径长度初始化
if(D[v]< MaxInt) Path [v]=v0; //v0和v之间有弧,将v的前驱置为v0
else Path [v]=-1; //如果v0和v之间无弧,则将v的前驱置为-1
}
S[v0]=true; //将v0加入S
D[v0]=0; //源点到源点的距离为0
/*―开始主循环,每次求得v0到某个顶点v的最短路径,将v加到S集―*/
int v=0;
for(int i=1;i<n; ++i)
{//对其余n?1个顶点,依次进行计算
int min= MaxInt;
for(int w=0;w<n; ++w)
if(!S[w]&&D[w]<min)
{v=w; min=D[w];} //选择一条当前的最短路径,终点为v
S[v]=true; //将v加入S
for(int w=0;w<n; ++w)
//更新从v0出发到集合V?S上所有顶点的最短路径长度
if(!S[w]&&(D[v]+G.arcs[v][w]<D[w]))
{
D[w]=D[v]+G.arcs[v][w]; //更新D[w]
Path [w]=v; //更改w的前驱为v
}
}
cout<<"以v0为起点的图的最短路径为:"<<endl;
for(int i=0;i<G.vexnum;i++)
{
cout<<"v0->v"<<i<<":";
if(D[i]!=MaxInt) //可以到达
{
cout<<D[i]<<endl;
}
else
{
cout<<"不可达,无最短路径"<<endl;
}
}
}
void Menu()
{
cout << "---------------------------" << endl;
cout << "****by 夏日****" << endl;
cout << "---------------------------" << endl;
cout << "1-----邻接表建立无向图 "<< endl;
cout << "2-----邻接表表示图的深度优先搜索遍历" << endl;
cout << "3-----邻接矩阵建立有向图 "<< endl;
cout << "4-----邻接矩阵表示图的深度优先搜索遍历" << endl;
cout << "5-----迪杰斯特拉算法计算最短路径(先用邻接矩阵建立有向图)" << endl;
cout << " 退出,输入一个负数!" << endl;
}
输出示例
1.邻接表建立无向图
2.邻接表表示图的深度优先搜索遍历
3.邻接矩阵建立有向图
4.邻接矩阵的深度优先搜索遍历
5.迪杰斯特拉算法