//用邻接表的方法存储网
#include<iostream>
#include<vector>
#include<string>
#include<malloc.h>
#define INF 0x3f3f3f
#define Node_MAX 20
using namespace std;
vector<int> PATH[Node_MAX];//存储路径
int D[Node_MAX];//存储路径长度
int P[Node_MAX];//存储过程中的路径长度
typedef struct ArcNode{
int adjvex;//指向的另外顶点位置
struct ArcNode *next;
int length;
}ArcNode;
typedef struct VNode{
char name;
ArcNode *first;
}VNode;
typedef struct{
VNode vexs[Node_MAX];//存储顶点
int vexnum,arcnum;//图的顶点个数,弧的个数
int kind;//图的类型,0代表无向图,1代表有向图
}LGraph;
int FindV(char v,VNode *p,int num)
{
for(int t=0;t<num;t++)
if(v==p[t].name) return t;
cout<<"ERROR:输入空的顶点,结束"<<endl;
exit(-1);
}
bool CreateDN(LGraph &G)
{
cout<<"请输入有向图的顶点个数和弧的数量"<<endl;
cin>>G.vexnum>>G.arcnum;
cout<<"请依次输入顶点的名称"<<endl;
for(int t=0;t<G.vexnum;t++)
{
cin>>G.vexs[t].name;
G.vexs[t].first=NULL;
}
ArcNode *a=(ArcNode *)malloc(sizeof(ArcNode)*G.arcnum);//弧结点分配空间
ArcNode **p=(ArcNode **)malloc(sizeof(ArcNode *)*G.vexnum);//*(p+t)指向过程中t顶点指向的最后弧结点
for(int t=0;t<G.arcnum;t++)
{
char v1,v2;
int i,j,x;
cout<<"请输入第"<<t+1<<"条弧的弧尾弧头名称及长度"<<endl;
cin>>v1>>v2>>x;
i=FindV(v1,G.vexs,G.vexnum);
j=FindV(v2,G.vexs,G.vexnum);
(a+t)->adjvex=j;(a+t)->length=x;(a+t)->next=NULL;//创建弧结点
if(G.vexs[i].first==NULL)
*(p+i)=G.vexs[i].first=a+t;
else
{
*(p+i)=(*(p+i))->next=a+t;
}
}
return true;
}
bool CreateUDN(LGraph &G)
{
cout<<"请输入无向图的顶点个数和弧的数量"<<endl;
cin>>G.vexnum>>G.arcnum;
cout<<"请依次输入顶点的名称"<<endl;
for(int t=0;t<G.vexnum;t++)
{
cin>>G.vexs[t].name;
G.vexs[t].first=NULL;
}
ArcNode *a=(ArcNode *)malloc(sizeof(ArcNode)*G.arcnum*2);//弧结点分配空间
ArcNode **p=(ArcNode **)malloc(sizeof(ArcNode *)*G.vexnum);//*(p+t)指向过程中t顶点指向的最后弧结点
for(int t=0;t<G.arcnum;t++)
{
char v1,v2;
int i,j,x;
cout<<"请输入第"<<t+1<<"条弧两端名称及长度"<<endl;
cin>>v1>>v2>>x;
i=FindV(v1,G.vexs,G.vexnum);
j=FindV(v2,G.vexs,G.vexnum);
(a+t)->adjvex=j;(a+t)->length=x;(a+t)->next=NULL;//创建弧结点
(a+t+G.arcnum)->adjvex=i;(a+t+G.arcnum)->length=x;(a+t+G.arcnum)->next=NULL;//创建弧结点
if(G.vexs[i].first==NULL)
*(p+i)=G.vexs[i].first=a+t;
else
{
*(p+i)=(*(p+i))->next=a+t;
}
if(G.vexs[j].first==NULL)
*(p+j)=G.vexs[j].first=a+t;
else
{
*(p+j)=(*(p+j))->next=a+t;
}
}
return true;
}
bool CreateLGraph(LGraph &G)
{
cout<<"请输入图的类型:有向图DN,无向图UDN"<<endl;
string temp;
cin>>temp;
if(!temp.compare("DN")) G.kind=1;
if(!temp.compare("UDN")) G.kind=0;
switch(G.kind)
{
case 0:CreateUDN(G);
break;
case 1:CreateDN(G);
break;
default:
cout<<"ERROR"<<endl;
exit(-1);
}
return true;
}
void DIJ(LGraph &G,char v)//算G图各顶点到v的最短路径
{
int w=FindV(v,G.vexs,G.vexnum);
for(int t=0;t<G.vexnum;t++)
{
PATH[t].push_back(w);
P[t]=INF;
D[t]=INF;
}
D[w]=0;
ArcNode *p=G.vexs[w].first;
while(p!=NULL)
{
P[p->adjvex]=p->length;
p=p->next;
}
for(int t=0;t<G.vexnum-1;t++) //需要进行G.vexnum-1次
{
int min=INF,e;
for(int i=0;i<G.vexnum;i++)
{
if(min>=P[i] && D[i]==INF){min=P[i];e=i;}
}
D[e]=min;
PATH[e].push_back(e);
p=G.vexs[e].first;
while(p!=NULL)
{
if(min+p->length < P[p->adjvex] && D[p->adjvex]==INF)
{P[p->adjvex]=min+p->length;PATH[p->adjvex]=PATH[e];}
p=p->next;
}
}
}
int main()
{
char v;
LGraph G;
CreateLGraph(G);
/* ArcNode *p;
for(int t=0;t<G.vexnum;t++)
{
cout<<G.vexs[t].name<<endl;
p=G.vexs[t].first;
while(p!=NULL)
{
cout<<G.vexs[p->adjvex].name<<" ";
p=p->next;
}
cout<<endl;
}
*/
cout<<"请输入单源最短路径的源顶点名称"<<endl;
cin>>v;
DIJ(G,v);
for(int t=0;t<G.vexnum;t++)
{
cout<<v<<"->"<<G.vexs[t].name<<endl;
for(vector<int>::iterator it=PATH[t].begin();it!=PATH[t].end();it++)
cout<<G.vexs[*it].name<<" ";
if(D[t]!=INF) cout<<endl<<D[t]<<endl;
else cout<<endl<<"无" <<endl;
}
return 0;
}
求单源的最短路径
最新推荐文章于 2023-01-06 10:11:54 发布