用c++实现基于vector的迪杰斯特拉算法

31 篇文章 0 订阅

本程序的实现是在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()函数创建元素时,是不能对元素进行复制的,此时访问的是非法内存。



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值