本程序的实现是在linux redhat,vmware下实现的,使用的是g++编译器,如何读者使用其他的编译器,可能需要小改一下代码~~
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<sstream>
#define INF 1147483646
#define maxn 50
using namespace std;
vector<int> edges[maxn];//the edges
struct Point{
string name;
int num;
Point(string name,int num):name(name),num(num){}
};
struct mp{
int pn;
vector<Point> point;
vector<int>* e;
mp(vector<Point> point,vector<int>* e):point(point),e(e),pn(point.size()){}
};
struct Trace{ //trace
vector<Point> point;
int length;
int num; //dest point num
Trace(int length=INF,int num=0):length(length),num(num){}
Trace& operator = (const Trace& B)
{
this->point=B.point;
this->length=B.length;
this->num=B.num;
}
};
void fangyi(int& a)
{
if(a>INF)
a=INF;
}
void inputpoint(vector<Point>& point)
{
printf("Please input the points:\n");
printf("Input quit to end input data.\n");
string a;
int i=0;
while(cin>>a)
{
if("quit"==a)
break;
point.push_back(Point(a,i++));
}
}
int findpnum(const vector<Point>& ps,string s)
{
int i=0;
while(i<ps.size())
{
if(s==ps[i].name)
break;
i++;
}
if(i>=ps.size())
return -1;
return i;
}
void inputedge(const vector<Point>& ps)
{
printf("Please input the edge format as:start point end point value:\n");
printf("Input quit to end input data.\n");
string a;
string st,en;
int va,tt;
for(int i=0;i<ps.size();i++) //create the edges
for(int j=0;j<ps.size();j++)
{
if(i==j)
edges[i].push_back(0);
else
edges[i].push_back(INF);
}
while(getline(cin,a))
{
if("quit"==a)
break;
stringstream s(a);
s>>st;
s>>en;
s>>va;
if(s>>tt)
{
printf("input error,again!\n");
continue;
}
int stnum=findpnum(ps,st);
int ennum=findpnum(ps,en);
if((-1==stnum)||(-1==ennum))
{
printf("the point is not exit!\n");
continue;
}
edges[stnum][ennum]=va;
edges[ennum][stnum]=va;
}
}
void djstl(const mp& map,vector<Trace>& t)
{
string s,e;
int sn,en;
printf("Input the start point and the end point:\n");
cin>>s>>e;
sn=findpnum(map.point,s);
en=findpnum(map.point,e);
for(int j=0;j<map.pn;j++)
{
t.push_back(Trace(INF,j));//create trace for each point
t[j].point.push_back(Point(map.point[sn].name,sn));
t[j].point.push_back(Point(map.point[j].name,j));
t[j].length=map.e[sn][j];
}
for(int i=1;i<map.pn;i++)
for(int i=1;i<map.pn;i++)
{
for(int j=1;j<map.pn;j++)//sort from min to max
{
int m=j;
if(t[m].length<t[m-1].length)
{
Trace tmp=t[m];
while(m>0)
{
if(tmp.length>=t[m-1].length)
break;
t[m]=t[m-1];
m--;
}
t[m]=tmp;
}
}
for(int k=i+1;k<map.pn;k++) //base on the i element
{
int sn=t[i].num;
int en=t[k].num;
int len=t[i].length+map.e[sn][en];//overflow!
fangyi(len);
if(len<t[k].length)//shorter than trace through t[i]
{
int tm=t[k].num;
t[k]=t[i];
t[k].num=tm;
t[k].point.push_back(Point(map.point[tm].name,tm));
t[k].length=len;
}
}
}
int j,q;
for(j=0;j<t.size();j++)
if(en==t[j].num)
break;
for(q=0;q<t[j].point.size()-1;q++)
{
{
cout<<t[j].point[q].name<<"->";
}
cout<<t[j].point[q].name<<endl;
cout<<"The whole length is"<<t[j].length<<endl;
}
int main()
{
vector<Point> p;
vector<Trace> t;//the start point to others' trace
inputpoint(p);
inputedge(p);
mp m(p,edges);
djstl(m,t);
return 0;
}
迪杰斯特拉算法概括起来就是,先找出起点到终点直接连接的长度,然后对长度排序(从小到大),然后以小的长度的路径间接构造到后面比较的节点的路径,因为如果存在b,使得a+b<c,那么只有当a<c时才存在(假设图为正权值的图)。外循环n-1次,每次以当前节点为间接构造的基本点。内循环n-k-1次,k为当前要找的更短路径的目的节点。
假设有图如下所示:
那么输入的计算的步骤是这样的:
可见,程序运行是没有问题的~~
注:要提醒读者的一点是,vector在还没有使用push_back()函数创建元素时,是不能对元素进行复制的,此时访问的是非法内存。