此算法没有采用《数据结构C语言版》中的存储结构,而是采用邻接表的方法存储图,经过改进,还能输出最短路径。
“Dijkstra.h”
#include<iostream>
using namespace std;
#define MAX_VEX_NUM 20
#define INFINITY INT_MAX
#define CANTFIND -1
class Path//记录源点到每一个点的路径
{
public:
Path();
int pathnode;
Path *next;
};
Path::Path()
{
pathnode=0;
next=NULL;
}
class NextNode//邻接表存储以某节点为尾的弧的相关信息
{
public:
NextNode();
int nextvex;//顶点编号
int weight;//弧上的权值
NextNode *next;//下一个节点的指针
};
NextNode::NextNode()
{
nextvex=weight=0;
next=NULL;
}
class VexNode//顶点相关信息
{
public:
VexNode();
char name;//顶点名称
bool choose;//标示此节点标示的最短路径是否已经被选择
int dist;//此节点当前存放的最短路径
NextNode *firstnext;
Path *path;
};
VexNode::VexNode()
{
choose=false;
dist=INFINITY;
firstnext=NULL;
path=NULL;
}
class VexBox//顶点集合
{
public:
VexBox();
int vexnum;//定点数目
VexNode vexbox[MAX_VEX_NUM];//顶点集合
};
VexBox::VexBox()
{
vexnum=0;
}
class ShortestPath_DIJ
{
public:
void ShortestPath();//接口函数
private:
void GetVex();//得到顶点信息
void GetArc();//得到弧的相关信息
void GetShortestPath();//得到最短路径
void PrintShortestPath();//打印最短路径
int GetShortestNode();//得到dist最小的节点
void UpdatePath(int,int);//更新路径
void ReMove(Path *);//销毁原路径
VexBox v;//顶点集合
int sourse;
};
void ShortestPath_DIJ::ShortestPath()
{
GetVex();//得到顶点信息
GetArc();//得到弧的相关信息
GetShortestPath();//得到最短路径
PrintShortestPath();//打印最短路径
}
void ShortestPath_DIJ::GetVex()//得到顶点信息
{
cout<<"Please Input The Name Of Each Vertex :"<<endl<<endl;
char name;
while(cin>>name)
{
v.vexbox[v.vexnum++].name=name;
}
cin.clear();
}
void ShortestPath_DIJ::GetArc()//得到弧的相关信息
{
cout<<"Please Input The Information Of Each Arc :"<<endl
<<"tail head weight"<<endl;
int tail,head,weight;
NextNode *newnode,*p;
while(cin>>tail>>head>>weight)
{
newnode=new NextNode;
newnode->nextvex=head;
newnode->weight=weight;
if((p=v.vexbox[tail].firstnext)==NULL)
{
v.vexbox[tail].firstnext=newnode;
}//if
else
{
while(p->next!=NULL)
p=p->next;
p->next=newnode;
}//else
}//while
cin.clear();
}
int ShortestPath_DIJ::GetShortestNode()//得到dist最小的节点
{
int ans=CANTFIND,min=INT_MAX;
for(int i=0;i<v.vexnum;i++)
{
if(v.vexbox[i].choose==false&&v.vexbox[i].dist<min)
{
min=v.vexbox[i].dist;
ans=i;
}//if
}//for
v.vexbox[ans].choose=true;//标记为已选择
return ans;
}
void ShortestPath_DIJ::ReMove(Path *p)//销毁原路径
{
if(p->next!=NULL)
ReMove(p->next);
delete p;
}
void ShortestPath_DIJ::UpdatePath(int a,int b)//更新路径
{
Path *p,*pt,*newpath;
ReMove(v.vexbox[b].path);
newpath=new Path;
newpath->pathnode=v.vexbox[a].path->pathnode;
v.vexbox[b].path=newpath;
p=v.vexbox[a].path->next;
pt=v.vexbox[b].path;
while(p!=NULL)
{
newpath=new Path;
newpath->pathnode=p->pathnode;
pt->next=newpath;
p=p->next;
pt=pt->next;
}
}
void ShortestPath_DIJ::GetShortestPath()//得到最短路径
{
Path *newpath,*pt;
cout<<"Please Input The Sourse :"<<endl;
while(cin>>sourse&&!(sourse<v.vexnum));//得到符合条件的源点
cout<<v.vexbox[sourse].name<<" : Start"<<endl;
v.vexbox[sourse].dist=0;//对源点的相关处理
for(int i=0;i<v.vexnum;i++)//初始化路径
{
if(i!=sourse)
{
newpath=new Path;
newpath->pathnode=sourse;
v.vexbox[i].path=newpath;
}
}
NextNode *p;
p=v.vexbox[sourse].firstnext;
while(p!=NULL)
{
newpath=new Path;
newpath->pathnode=p->nextvex;
v.vexbox[p->nextvex].path->next=newpath;
v.vexbox[p->nextvex].dist=p->weight;
p=p->next;
}
int ncase=v.vexnum-1;
int node;
while(ncase--)//处理源点到其他点的最短路径长度
{
node=GetShortestNode();//获得当前情况下未被选择的最短边
if(node==CANTFIND)//控制跳出
break;
p=v.vexbox[node].firstnext;
while(p!=NULL)//如有必要修改和该顶点相关的节点的Dist值
{
if(v.vexbox[node].dist+p->weight<v.vexbox[p->nextvex].dist)
{
v.vexbox[p->nextvex].dist=v.vexbox[node].dist+p->weight;
UpdatePath(node,p->nextvex);
newpath=new Path;
newpath->pathnode=p->nextvex;
pt=v.vexbox[p->nextvex].path;
while(pt->next!=NULL)
pt=pt->next;
pt->next=newpath;
}
p=p->next;
}
}
}
void ShortestPath_DIJ::PrintShortestPath()//打印最短路径
{
Path *p;
for(int i=0;i<v.vexnum;i++)
{
if(i!=sourse)
{
p=v.vexbox[i].path;
cout<<v.vexbox[i].name<<" : ";
if(v.vexbox[i].dist==INFINITY)
cout<<"∞"<<endl;
else
{
cout<<v.vexbox[i].dist<<" Path :";//打印路径
cout<<v.vexbox[p->pathnode].name;
p=p->next;
while(p!=NULL)
{
cout<<"->"<<v.vexbox[p->pathnode].name;
p=p->next;
}
cout<<endl;
}
}//if
}//for
}
“mian.cpp”
#include"Dijkstra.h"
int main()
{
ShortestPath_DIJ d;
d.ShortestPath();
system("pause");
}