数据结构课程设计,根据之前数据结构实践报告图的遍历修改而成,增加了对图使用dijkstra最短路径算法并记录路径,增加了交互界面,功能选择,异常处理等内容。具体使用邻接矩阵实现,邻接表未被调用但保留代码。
原代码请移步:数据结构图的建立
以上链接包括了代码中保留部分,各个模块包括建图(邻接矩阵、邻接表),BFS广搜,DFS模块都有说明。本文仅说明代码增加内容,交互界面异常处理和dijkstra最短路径计算,记录应用。
最短路径代码:
void dijkstra(MGraph G)
{
string tmp;
int pre[108];///父亲记录数组,回溯寻找路径
int dist[MAX_VERTEX_NUM],s;///最短路数组
bool vis[MAX_VERTEX_NUM];///标记数组
printf("请输入该图起点:");
while(cin>>tmp)///最短路源点
{
if(tmp=="END")break;
s=LocateVex(G,tmp);
if(s==-1)
{
printf("输入的起点不存在,请重新输入\n");
continue;
}
for(int i=0; i<G.vexnum; i++)pre[i]=s;///路径父亲初始化
memset(vis,false,sizeof(vis));
memset(dist,0x3f,sizeof(dist));
for(int i=0; i<G.vexnum; i++)///所有点到达起点的距离
dist[i]=G.arcs[s][i].adj;
dist[s]=0;///标记起点长度为0
vis[s]=true;///标记走过
for(int i=1; i<G.vexnum; i++)///遍历n-1次
{
int minn=0x7fffffff,mini;
for(int j=0; j<G.vexnum; j++)///这里是要遍历所有的点,因为不一定是第0个点作为起点
{
if(!vis[j]&& dist[j] < minn)
{
minn=dist[j];
mini=j;
}
}
vis[mini]=true;
for(int j=0; j<G.vexnum; j++)
{
if(dist[j]>dist[mini]+G.arcs[mini][j].adj)
{
dist[j]=dist[mini]+G.arcs[mini][j].adj;
pre[j]=mini;
}
// dist[j]=dist[j]<(dist[mini]+G.arcs[mini][j].adj)?dist[j]:(dist[mini]+G.arcs[mini][j].adj);
// printf("**%d %d\n",dist[j],dist[mini]+G.arcs[mini][j].adj);
}
}
cout<<"从源点"<<G.vexs[s]<<"到达所有位置的最短路径:\n";
for(int i=0; i<G.vexnum; i++)
{
if(i!=s)
{
cout<<"到达"<<G.vexs[i]<<"的最短路径距离:"<<dist[i]<<endl;
int step=0,road[108],tmp=i;
while(pre[tmp]!=tmp)///回溯寻找路径
{
road[step++]=pre[tmp];
tmp=pre[tmp];
}
printf("最短路径为:");
for(int j=step-1; j>=0; j--) cout<<G.vexs[road[j]]<<" ";
cout<<G.vexs[i]<<endl;
}
}
printf("*********输入新起点搜索起点重新遍历*********\n");
printf("*********输入END结束最短路径计算*********\n");
printf("请输入操作:");
}
printf("==============================================================\n");
printf("|| 1.深度优先搜索遍历 ||\n");
printf("|| 2.广度优先搜索遍历 ||\n");
printf("|| 3.最短路径计算(仅带权图) ||\n");
printf("|| 4.结束程序 ||\n");
printf("|| 5.重新建图 ||\n");
printf("==============================================================\n");
printf("请输入对图的操作:\n");
}
邻接矩阵基本类型的定义:
typedef struct ArcCell///弧(邻接矩阵)
{
int adj;
InfoType *info;
} ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct///图(邻接矩阵)
{
string vexs[MAX_VERTEX_NUM];///结点名
AdjMatrix arcs; ///邻接矩阵
int vexnum,arcnum; ///结点数,弧数
GraphKind kind;
} MGraph;
带权无向网的建立:
Status CreateUDN(MGraph &G)///邻接矩阵(建立带权无向网)
{
int IncInfo;
printf("建立带权无向网,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
{
if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
}
printf("请为从1至%d个结点命名:\n",G.vexnum);
for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
for(int i=0; i<G.vexnum; i++)
for(int j=0; j<G.vexnum; j++)
G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
string v1,v2;
printf("请输入%d组相互依附的两结点与边权(x<--->y 边权:z):\n",G.arcnum);
int w;///边权
for(int k=0; k<G.arcnum; k++)
{
cout<<"第"<<k+1<<"条边:";
cin>>v1>>v2>>w;
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);
if(i==-1||j==-1||w<=0||w>1000000000)
{
if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入\n");
k--;
continue;
}
G.arcs[i][j].adj=w;///带权
if(IncInfo)scanf("%s",G.arcs[i][j].info);
G.arcs[j][i]=G.arcs[i][j];///无向图,结构体赋值
}
return OK;
}
完整代码:
#include<iostream>
#include<stdio.h>
#include <time.h>
#include<string>
#include<stdlib.h>
#include<queue>
#include<string.h>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAX_VERTEX_NUM 105
#define INFINITY 0X3f3f3f3f
typedef char InfoType;
typedef int Status;
typedef int Boolean;
typedef string VertexType;
typedef enum {DG,DN,UDG,UDN} GraphKind;
Boolean visited[MAX_VERTEX_NUM];
typedef struct ArcCell///弧(邻接矩阵)
{
int adj;
InfoType *info;
} ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct///图(邻接矩阵)
{
string vexs[MAX_VERTEX_NUM];///结点名
AdjMatrix arcs; ///邻接矩阵
int vexnum,arcnum; ///结点数,弧数
GraphKind kind;
} MGraph;
Status (*VisitFunc)(MGraph G,int v);
Status LocateVex(MGraph G,string name)///获取结点标号
{
for(int i=0; i<G.vexnum; i++)
if(name==G.vexs[i])return i;
return -1;
}
Status CreateDG(MGraph &G)///邻接矩阵(建立无权有向图)
{
int IncInfo;
printf("建立无权有向图,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
{
if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
}
printf("请为从1至%d个结点命名:\n",G.vexnum);
for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
for(int i=0; i<G.vexnum; i++)
for(int j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
string v1,v2;
printf("请输入%d组由左指向右的有向边(x--->y):\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cout<<"第"<<k+1<<"条边:";
cin>>v1>>v2;
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);
if(i==-1||j==-1)
{
if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
k--;
continue;
}
G.arcs[i][j].adj=TRUE;///无权
if(IncInfo)scanf("%s",G.arcs[i][j].info);
}
return OK;
}
Status CreateDN(MGraph &G)///邻接矩阵(建立带权有向网)
{
int IncInfo;
printf("建立带权有向网,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
{
if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
}
printf("请为从1至%d个结点命名:\n",G.vexnum);
for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
for(int i=0; i<G.vexnum; i++)
for(int j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
string v1,v2;
int w;
printf("请输入%d组由左指向右的有向边与边权(x--->y 边权:z):\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cout<<"第"<<k+1<<"条边:";
cin>>v1>>v2>>w;
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);
if(i==-1||j==-1||w<=0||w>1000000000)
{
if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入\n");
k--;
continue;
}
G.arcs[i][j].adj=w;///带权
if(IncInfo)scanf("%s",G.arcs[i][j].info);
}
return OK;
}
Status CreateUDG(MGraph &G)///邻接矩阵(建立无权无向图)
{
int IncInfo;
printf("建立无权无向图,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
{
if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
}
printf("请为从1至%d个结点命名:\n",G.vexnum);
for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
for(int i=0; i<G.vexnum; i++)
for(int j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
string v1,v2;
printf("请输入%d组相互依附的两结点:\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cout<<"第"<<k+1<<"条边:";
cin>>v1>>v2;
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);
if(i==-1||j==-1)
{
if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
k--;
continue;
}
G.arcs[i][j].adj=TRUE;///无权
if(IncInfo)scanf("%s",G.arcs[i][j].info);
G.arcs[j][i]=G.arcs[i][j];///无向图,结构体赋值
}
return OK;
}
Status CreateUDN(MGraph &G)///邻接矩阵(建立带权无向网)
{
int IncInfo;
printf("建立带权无向网,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
{
if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
}
printf("请为从1至%d个结点命名:\n",G.vexnum);
for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
for(int i=0; i<G.vexnum; i++)
for(int j=0; j<G.vexnum; j++)
G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
string v1,v2;
printf("请输入%d组相互依附的两结点与边权(x<--->y 边权:z):\n",G.arcnum);
int w;///边权
for(int k=0; k<G.arcnum; k++)
{
cout<<"第"<<k+1<<"条边:";
cin>>v1>>v2>>w;
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);
if(i==-1||j==-1||w<=0||w>1000000000)
{
if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入\n");
k--;
continue;
}
G.arcs[i][j].adj=w;///带权
if(IncInfo)scanf("%s",G.arcs[i][j].info);
G.arcs[j][i]=G.arcs[i][j];///无向图,结构体赋值
}
return OK;
}
void DFS(MGraph G,int v)///邻接矩阵DFS
{
visited[v]=TRUE;
VisitFunc(G,v);
for(int w=0; w<G.vexnum; w++)
if(G.arcs[v][w].adj!=INFINITY&&!visited[w])DFS(G,w);
}
void DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))
{
VisitFunc=Visit;
printf("请输入深度优先搜索起始结点:\n");
string st;
while(cin>>st)
{
if(st=="END")break;
int tmp=LocateVex(G,st);
if(tmp==-1)
{
printf("输入的起点不存在,请重新输入\n");
continue;
}
for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
printf("深度优先搜索遍历序列:\n");
DFS(G,tmp);
for(int v=0; v<G.vexnum; v++)if(!visited[v])DFS(G,v);
printf("\n");
printf("*********输入新起点搜索起点重新遍历*********\n");
printf(" **********输入END结束深度优先搜索*********\n");
printf("请输入操作:");
}
printf("==============================================================\n");
printf("|| 1.深度优先搜索遍历 ||\n");
printf("|| 2.广度优先搜索遍历 ||\n");
printf("|| 3.最短路径计算(仅带权图) ||\n");
printf("|| 4.结束程序 ||\n");
printf("|| 5.重新建图 ||\n");
printf("==============================================================\n");
printf("请输入对图的操作:\n");
}
void BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))///邻接矩阵BFS
{
queue<int>Q;
printf("请输入广度优先搜索起始结点:\n");
string st;
while(cin>>st)
{
if(st=="END")break;
int temp=LocateVex(G,st);
if(temp==-1)
{
printf("输入的起点不存在,请重新输入\n");
continue;
}
for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
while(!Q.empty())Q.pop();
printf("广度优先搜索遍历序列:\n");
Visit(G,temp);
Q.push(temp);
visited[temp]=TRUE;
while(!Q.empty())
{
int tmp=Q.front();
Q.pop();
for(int w=0; w<G.vexnum; w++)
{
if(!visited[w]&&G.arcs[tmp][w].adj!=INFINITY)
{
visited[w]=TRUE;
Visit(G,w);
Q.push(w);
}
}
}
for(int v=0; v<G.vexnum; v++)///剩余连通分量
{
if(!visited[v])
{
visited[v]=TRUE;
Visit(G,v);
Q.push(v);
while(!Q.empty())
{
int tmp=Q.front();
Q.pop();
for(int w=0; w<G.vexnum; w++)
{
if(!visited[w]&&G.arcs[tmp][w].adj!=INFINITY)
{
visited[w]=TRUE;
Visit(G,w);
Q.push(w);
}
}
}
}
}
printf("\n");
printf("*********输入新起点搜索起点重新遍历*********\n");
printf("*********输入END结束广度优先搜索*********\n");
printf("请输入操作:");
}
printf("==============================================================\n");
printf("|| 1.深度优先搜索遍历 ||\n");
printf("|| 2.广度优先搜索遍历 ||\n");
printf("|| 3.最短路径计算(仅带权图) ||\n");
printf("|| 4.结束程序 ||\n");
printf("|| 5.重新建图 ||\n");
printf("==============================================================\n");
printf("请输入对图的操作:\n");
}
Status CreateGraph(MGraph &G)///邻接矩阵
{
printf("**********************************************\n");
printf("* *\n");
printf("* 1:无权有向图 *\n");
printf("* 2:带权有向网 *\n");
printf("* 3:无权无向图 *\n");
printf("* 4:带权无向网 *\n");
printf("* *\n");
printf("**********************************************\n");
printf("请输入建图类型:");
scanf("%d",&G.kind);///输入图的种类
system("cls");
switch(G.kind-1)
{
case DG:
return CreateDG(G);
case DN:
return CreateDN(G);
case UDG:
return CreateUDG(G);
case UDN:
return CreateUDN(G);
default:
return ERROR;
}
}
Status visit(MGraph G,int v)///邻接矩阵遍历
{
cout<<G.vexs[v]<<' ';
}
///===========================================================================
typedef struct ArcNode///弧(邻接表)
{
int adjvex; ///当前弧指向的顶点
int info; ///权值
struct ArcNode *nextarc;///下一条当前顶点为出度的弧
} ArcNode;
typedef struct VNode///点(邻接表)
{
VertexType data;///结点名
ArcNode *firstarc;///该点的第一条出边
} VNode,AdjList[MAX_VERTEX_NUM];
typedef struct///图(邻接表)
{
AdjList vertices;///点的邻接表(数组)
int vexnum,arcnum;
int kind;
} ALGraph;
Status (*VisitFunc_2)(ALGraph G,int v);
void ArcAdd_sort(ALGraph &G,int v1,int v2,int w)///从大到小顺序建立邻接表
{
ArcNode *p,*h,*q;
p=new ArcNode;
p->adjvex=v2;
p->info=w;
p->nextarc=NULL;
h=q=G.vertices[v1].firstarc;
if(q==NULL)G.vertices[v2].firstarc=p;
else
{
if(p->adjvex > q->adjvex)///邻接表按结点序号从大到小排列
{
p->nextarc=q;
G.vertices[v2].firstarc=p;
}
else
{
while(G.vertices[v2].firstarc!=NULL&&q->nextarc!=NULL&&p->adjvex < q->adjvex)
{
h=q;
q=q->nextarc;
}
if(q->nextarc==NULL&&p->adjvex < q->adjvex) q->nextarc=p;
else
{
p->nextarc=q;
h->nextarc=p;
}
}
}
}
void ArcAdd(ALGraph &G,int v1,int v2,int w)///加边
{
ArcNode *p,*q;
p=new ArcNode;
p->adjvex=v2;
p->info=w;
p->nextarc=NULL;
q=G.vertices[v1].firstarc;
if(q==NULL) G.vertices[v1].firstarc=p;///若第一条依附v2顶点的弧还未存在,新加入的边作为第一条依附弧
else///否则顺着链表向后查找
{
while(q->nextarc!=NULL) q=q->nextarc;
q->nextarc=p;
}
}
int LocateVex_2(ALGraph G,string name)///获取结点标号
{
for(int i=0; i<G.vexnum; i++)
if(name==G.vertices[i].data)return i;
return -1;
}
Status CreateDG_2(ALGraph &G)///邻接表(建立无权有向图)
{
printf("建立无权有向图,请依次输入总结点数、总边数:\n");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("请为从1至n个结点命名:\n");
for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
string v1,v2;
printf("请输入%d组由左指向右的有向边:\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cin>>v1>>v2;
int i=LocateVex_2(G,v1);///获取标号
int j=LocateVex_2(G,v2);
ArcAdd(G,i,j,1);
}
return OK;
}
Status CreateDN_2(ALGraph &G)///邻接表(建立带权有向网)
{
printf("建立带权有向网,请依次输入总结点数、总边数:\n");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("请为从1至n个结点命名:\n");
for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
string v1,v2;
int w;
printf("请输入%d组由左指向右的有向边与边权:\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cin>>v1>>v2>>w;
int i=LocateVex_2(G,v1);///获取标号
int j=LocateVex_2(G,v2);
ArcAdd(G,i,j,w);
}
return OK;
}
Status CreateUDG_2(ALGraph &G)///邻接表(建立无权无向图)
{
printf("建立无权无向图,请依次输入总结点数、总边数:\n");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("请为从1至n个结点命名:\n");
for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
string v1,v2;
printf("请输入%d组相互依附的两结点:\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cin>>v1>>v2;
int i=LocateVex_2(G,v1);///获取标号
int j=LocateVex_2(G,v2);
ArcAdd(G,i,j,1);///无向边
ArcAdd(G,j,i,1);
}
return OK;
}
Status CreateUDN_2(ALGraph &G)///邻接表(建立带权无向网)
{
printf("建立带权无向网,请依次输入总结点数、总边数:\n");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("请为从1至%d个结点命名:\n",G.vexnum);
for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
string v1,v2;
int w;
printf("请输入%d组相互依附的两结点与边权:\n",G.arcnum);
for(int k=0; k<G.arcnum; k++)
{
cin>>v1>>v2>>w;
int i=LocateVex_2(G,v1);///获取标号
int j=LocateVex_2(G,v2);
ArcAdd(G,i,j,w);///无向边
ArcAdd(G,j,i,w);
}
return OK;
}
int FirstAdjVex(ALGraph G,int v)
{
if(G.vertices[v].firstarc) return G.vertices[v].firstarc->adjvex;
return -1;
}
int NextAdjVex(ALGraph G,int v,int w)
{
ArcNode *p=G.vertices[v].firstarc;
while(p->adjvex!=w&&p->nextarc!=NULL)p=p->nextarc;
if(p->nextarc==NULL)return -1;
return p->nextarc->adjvex;
}
void DFS_2(ALGraph G,int v)///邻接表DFS
{
visited[v]=TRUE;
VisitFunc_2(G,v);
for(int w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))
if(!visited[w])DFS_2(G,w);
}
void DFSTraverse_2(ALGraph G,Status (*Visit)(ALGraph G,int v))
{
VisitFunc_2=Visit;
printf("请输入深度优先搜索起始结点:\n");
for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
string st;
cin>>st;
int tmp=LocateVex_2(G,st);
printf("深度优先搜索遍历序列:\n");
DFS_2(G,tmp);
for(int v=0; v<G.vexnum; v++)if(!visited[v])DFS_2(G,v);
printf("\n");
}
void BFSTraverse_2(ALGraph G,Status (*Visit)(ALGraph G,int v))///邻接表BFS
{
for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
queue<int>Q;
printf("请输入广度优先搜索起始结点:\n");
string st;
cin>>st;
printf("广度优先搜索遍历序列:\n");
int temp=LocateVex_2(G,st);
Visit(G,temp);
Q.push(temp);
visited[temp]=TRUE;
while(!Q.empty())
{
int tmp=Q.front();
Q.pop();
for(int w=FirstAdjVex(G,tmp); w>=0; w=NextAdjVex(G,tmp,w))
{
if(!visited[w])
{
visited[w]=TRUE;
Visit(G,w);
Q.push(w);
}
}
}
for(int v=0; v<G.vexnum; v++)///剩余连通分量
{
if(!visited[v])
{
visited[v]=TRUE;
Visit(G,v);
Q.push(v);
while(!Q.empty())
{
int tmp=Q.front();
Q.pop();
for(int w=FirstAdjVex(G,tmp); w>=0; w=NextAdjVex(G,tmp,w))
{
if(!visited[w])
{
visited[w]=TRUE;
Visit(G,w);
Q.push(w);
}
}
}
}
}
printf("\n");
}
void PrintGraph(ALGraph G)///输出邻接表
{
cout<<"图的创建完成,该图的邻接表表示为:"<<endl;
ArcNode *p;
for(int i=0; i<G.vexnum; i++)
{
if(G.vertices[i].firstarc == NULL)
cout<<i<<":"<<G.vertices[i].data<<"-->NULL"<<endl;
else
{
p = G.vertices[i].firstarc;
cout<<i<<":"<<G.vertices[i].data<<"-->";
while(p->nextarc!=NULL)
{
cout<<p->adjvex<<"-->";
p = p->nextarc;
}
cout<<p->adjvex<<"-->NULL"<<endl;
}
}
}
Status CreateGraph_2(ALGraph &G)///邻接表
{
printf("**********************************************\n");
printf("* *\n");
printf("* 1:无权有向图 *\n");
printf("* 2:带权有向网 *\n");
printf("* 3:无权无向图 *\n");
printf("* 4:带权无向网 *\n");
printf("* *\n");
printf("**********************************************\n");
printf("请输入建图类型:");
scanf("%d",&G.kind);///输入图的种类
system("cls");
switch(G.kind-1)
{
case DG:
return CreateDG_2(G);
case DN:
return CreateDN_2(G);
case UDG:
return CreateUDG_2(G);
case UDN:
return CreateUDN_2(G);
default:
return ERROR;
}
}
Status visit_2(ALGraph G,int v)///邻接表遍历
{
cout<<G.vertices[v].data<<' ';
}
///===============================================================================
void dijkstra(MGraph G)
{
string tmp;
int pre[108];
int dist[MAX_VERTEX_NUM],s;///最短路数组
bool vis[MAX_VERTEX_NUM];
printf("请输入该图起点:");
while(cin>>tmp)///最短路源点
{
if(tmp=="END")break;
s=LocateVex(G,tmp);
if(s==-1)
{
printf("输入的起点不存在,请重新输入\n");
continue;
}
for(int i=0; i<G.vexnum; i++)pre[i]=s;///路径父亲初始化
memset(vis,false,sizeof(vis));
memset(dist,0x3f,sizeof(dist));
for(int i=0; i<G.vexnum; i++)///所有点到达起点的距离
dist[i]=G.arcs[s][i].adj;
dist[s]=0;///标记起点长度为0
vis[s]=true;///标记走过
for(int i=1; i<G.vexnum; i++)///遍历n-1次
{
int minn=0x7fffffff,mini;
for(int j=0; j<G.vexnum; j++)///这里是要遍历所有的点,因为不一定是第0个点作为起点
{
if(!vis[j]&& dist[j] < minn)
{
minn=dist[j];
mini=j;
}
}
vis[mini]=true;
for(int j=0; j<G.vexnum; j++)
{
if(dist[j]>dist[mini]+G.arcs[mini][j].adj)
{
dist[j]=dist[mini]+G.arcs[mini][j].adj;
pre[j]=mini;
}
// dist[j]=dist[j]<(dist[mini]+G.arcs[mini][j].adj)?dist[j]:(dist[mini]+G.arcs[mini][j].adj);
// printf("**%d %d\n",dist[j],dist[mini]+G.arcs[mini][j].adj);
}
}
cout<<"从源点"<<G.vexs[s]<<"到达所有位置的最短路径:\n";
for(int i=0; i<G.vexnum; i++)
{
if(i!=s)
{
cout<<"到达"<<G.vexs[i]<<"的最短路径距离:"<<dist[i]<<endl;
int step=0,road[108],tmp=i;
while(pre[tmp]!=tmp)
{
road[step++]=pre[tmp];
tmp=pre[tmp];
}
printf("最短路径为:");
for(int j=step-1; j>=0; j--) cout<<G.vexs[road[j]]<<" ";
cout<<G.vexs[i]<<endl;
}
}
printf("*********输入新起点搜索起点重新遍历*********\n");
printf("*********输入END结束最短路径计算*********\n");
printf("请输入操作:");
}
printf("==============================================================\n");
printf("|| 1.深度优先搜索遍历 ||\n");
printf("|| 2.广度优先搜索遍历 ||\n");
printf("|| 3.最短路径计算(仅带权图) ||\n");
printf("|| 4.结束程序 ||\n");
printf("|| 5.重新建图 ||\n");
printf("==============================================================\n");
printf("请输入对图的操作:\n");
}
int main()
{
while(true)
{
MGraph G1;
while(!CreateGraph(G1))///邻接矩阵
printf("输入错误\n");
// for(int i=0; i<G1.vexnum; i++)
// for(int j=0; j<G1.vexnum; j++)
// printf("%15d%c",G1.arcs[i][j].adj,j==G1.vexnum-1?'\n':' ');
int con;
printf("==============================================================\n");
printf("|| 1.深度优先搜索遍历 ||\n");
printf("|| 2.广度优先搜索遍历 ||\n");
printf("|| 3.最短路径计算(仅带权图) ||\n");
printf("|| 4.结束程序 ||\n");
printf("|| 5.重新建图 ||\n");
printf("==============================================================\n");
printf("请输入对图的操作:\n");
while(scanf("%d",&con)!=EOF)
{
system("cls");
if(con==1)
DFSTraverse(G1,visit);///深搜邻接矩阵
else if(con==2)
BFSTraverse(G1,visit);///广搜邻接矩阵
else if(con==3&&(G1.kind==2||G1.kind==4))
dijkstra(G1);
else if(con==4)
return 0;
else if(con==5)
break;
else
printf("输入错误,可能输入错误的指令或对无权图求最短路\n");
}
printf("请重新建图!\n");
//// ALGraph G2;///邻接表
// CreateGraph_2(G2);
// PrintGraph(G2);///输出邻接表
// DFSTraverse_2(G2,visit_2);///邻接表深搜
// BFSTraverse_2(G2,visit_2);///邻接表广搜
}
}
/* 3 8 9 V1 V2 V3 V4 V5 V6 V7 V8 V1 V2 V2 V4 V4 V8 V8 V5 V2 V5 V1 V3 V3 V6 V3 V7 V6 V7 V1 V2 1 V1 V3 12 V2 V3 9 V2 V4 3 V3 V5 5 V4 V3 4 V4 V5 13 V4 V6 15 V5 V6 4 */