狄杰斯特拉算法
 Dijkstra(狄杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。
问题描述
  在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
狄杰斯特拉算法
  狄杰斯特拉(Dijkstra)算法思想  
按路径长度递增次序产生最短路径算法:
  把V分成两组:
  (1)S:已求出最短路径的顶点的集合
  (2)V-S=T:尚未确定最短路径的顶点集合
  将T中顶点按最短路径递增的次序加入到S中,
  保证:(1)从源点V0到S中各顶点的最短路径长度都不大于
  从V0到T中任何顶点的最短路径长度
  (2)每个顶点对应一个距离值
  S中顶点:从V0到此顶点的最短路径长度
  T中顶点:从V0到此顶点的只包括S中顶点作中间
  顶点的最短路径长度
  依据:可以证明V0到T中顶点Vk的最短路径,或是从V0到Vk的
  直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和
  (反证法可证)
  求最短路径步骤
  算法步骤如下:
  1. 初使时令 S={V0},T={其余顶点},T中顶点对应的距离值
  若存在<V0,Vi>,d(V0,Vi)为<V0,Vi>弧上的权值
  若不存在<V0,Vi>,d(V0,Vi)为∝
  2. 从T中选取一个其距离值为最小的顶点W且不在S中,加入S
  3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的
  距离值缩短,则修改此距离值
  重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止

狄杰斯特拉算法的原理

  首先,引进一个辅助向量D,它的每个分量D表示当前所找到的从始点v到每个终点vi的最短路径的长度。如D[3]=2表示从始点v到终点3的路径相对最小长度为2。这里强调相对就是说在算法过程中D的值是在不断逼近最终结果但在过程中不一定就等于最短路径长度。它的初始状态为:若从v到vi有弧,则D为弧上的权值;否则置D为∞。显然,长度为 D[j]=Min{D | vi∈V} 的路径就是从v出发的长度最短的一条最短路径。此路径为(v,vj)。 那么,下一条长度次短的最短路径是哪一条呢?假设该次短路径的终点是vk,则可想而知,这条路径或者是(v,vk),或者是(v,vj,vk)。它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。 一般情况下,假设S为已求得最短路径的终点的集合,则可证明:下一条最短路径(设其终点为X)或者是弧(v,x),或者是中间只经过S中的顶点而最后到达顶点X的路径。因此,下一条长度次短的最短路径的长度必是D[j]=Min{D | vi∈V-S} 其中,D或者是弧(v,vi)上的权值,或者是D[k](vk∈S)和弧(vk,vi)上的权值之和。 狄杰斯特拉算法描述如下: 1)arcs表示弧上的权值。若不存在,则置arcs为∞(在本程序中为MAXCOST)。S为已找到从v出发的最短路径的终点的集合,初始状态为空集。那么,从v出发到图上其余各顶点vi可能达到的最短路径长度的初值为D=arcs[Locate Vex(G,v),i] vi∈V 2)选择vj,使得D[j]=Min{D | vi∈V-S} 3)修改从v出发到集合V-S上任一顶点vk可达的最短路径长度。

打开IDE

我们创建一个工程

类声名如下

#if !defined(AFX_GRAPH_H__EDF8E290_EF85_4726_851D_F684E5602E43__INCLUDED_)
#define AFX_GRAPH_H__EDF8E290_EF85_4726_851D_F684E5602E43__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000//图的相关数据类型的定义graph.h
//最多顶点数
const int MaxV=10;
//最大权值
const int MaxValue=99;
//定义邻接表中的边结点类型
struct edgenode {int adjvex;   //邻接点域int weight;   //权值域edgenode* next;//指向下一个边结点的链域
};
//定义邻接表类型
typedef edgenode** adjlist;
//邻接矩阵类定义
class AdjMatrix
{private:
char g[MaxV];//顶点信息数组
int size;//当前顶点数
int GA[MaxV][MaxV];//定义邻接矩阵GA
int numE;//当前边数
public://构造函数,初始化图的邻接矩阵AdjMatrix(int n,int k2);//判断图空否bool GraphEmpty() {return size==0;}//取当前顶点数int NumV() {return size;}//取当前边数int NumEdges() {return numE;}//取顶点i的值char GetValue(const int i);//取弧<v1,v2>的权int GetWeight(const int v1,const int v2);//在位置pos处插入顶点Vvoid InsertV(const char &V,int pos);//插入弧<v1,v2>,权为weightvoid InsertEdge(const int v1,const int v2,int weight);//删除顶点i与顶点i相关的所有边char DeleteVE(const int i);//删除弧<v1,v2>void DeleteEdge(const int v1,const int v2);//建立图的邻接矩阵void CreateMatrix(int n, int k1,int k2);//k1为0则无向否则为有向,k2为0则无权否则为有权//从初始点vi出发深度优先搜索由邻接矩阵表示的图void dfsMatrix(bool*& visited,int i,int n,int k2);//从初始点vi出发广度优先搜索由邻接矩阵表示的图void bfsMatrix(bool*& visited,int i,int n,int k2);//由图的邻接矩阵得到图的邻接表void graphChange(adjlist &GL,int n,int k2);//检查输入的边序号是否越界,若越界则重输void Check(int n,int& i,int& j);//由图的邻接矩阵建立图void Creatgraph(int n,int k2);//对非连通图进行深度优先搜索void dfsMatrix(int n,int k2);//对非连通图进行广度优先搜索void bfsMatrix(int n,int k2);
};#endif // !defined(AFX_GRAPH_H__EDF8E290_EF85_4726_851D_F684E5602E43__INCLUDED_)

类实现如下

#include "stdafx.h"
#include "graph.h"//图的相关运算的实现graph.cpp
#include"graph.h"
//构造函数,初始化图的邻接矩阵
AdjMatrix::AdjMatrix(int n,int k2)
{int i,j;if(k2==0){//初始化无(有)向无权图for(i=0;i<n;i++)for(j=0;j<n;j++)GA[i][j]=0;}else {//初始化无(有)向有权图for(i=0;i<n;i++)for(j=0;j<n;j++)if(i==j) GA[i][j]=0;else GA[i][j]=MaxValue;}size=numE=0;
}
//建立图的邻接矩阵
void AdjMatrix::CreateMatrix(int n,int k1,int k2)
//k1为0则无向否则为有向,k2为0则无权否则为有权
{int i,j,k,e,w;cout<<"输入图的总边数:";cin>>e;if(k1==0 && k2==0) { //建立无向无权图cout<<"输入"<<e<<"条无向无权边的起点和终点序号!"<<endl;for(k=1; k<=e; k++) {cin>>i>>j;Check(n,i,j);GA[i][j]=GA[j][i]=1;}}else if(k1==0 && k2!=0) { //建立无向有权图cout<<"输入"<<e<<"条无向带权边的起点和终点序号及权值!"<<endl;for(k=1; k<=e; k++) {cin>>i>>j>>w;Check(n,i,j);GA[i][j]=GA[j][i]=w;}}else if(k1!=0 && k2==0) { //建立有向无权图cout<<"输入"<<e<<"条有向无权边的起点和终点序号!"<<endl;for(k=1; k<=e; k++) {cin>>i>>j;Check(n,i,j);GA[i][j]=1;}}else if(k1!=0 && k2!=0) { //建立有向有权图cout<<"输入"<<e<<"条有向有权边的起点和终点序号及权值!"<<endl;for(k=1; k<=e; k++) {cin>>i>>j>>w;Check(n,i,j);GA[i][j]=w;}}numE=e;   cout<<"创建后的邻接矩阵:\n";   for(i=0;i<n;i++){for(j=0;j<n;j++)cout<<setw(4)<<GA[i][j];cout<<endl;}
}
//从初始点vi出发深度优先搜索由邻接矩阵表示的图
void AdjMatrix::dfsMatrix(bool*& visited,int i,int n,int k2)
{cout<<g[i]<<':'<<i<<"  ";visited[i]=true;        //标记vi已被访问过for(int j=0; j<n; j++)  //依次搜索vi的每个邻接点if(k2==0){if(i!=j&&GA[i][j]!=0&&!visited[j])dfsMatrix(visited,j,n,k2);}elseif(i!=j&&GA[i][j]!=MaxValue&&!visited[j])dfsMatrix(visited,j,n,k2);
}
//从初始点vi出发广度优先搜索由邻接矩阵表示的图
void AdjMatrix::bfsMatrix(bool*& visited,int i,int n,int k2)
{const int MaxLength=30;//定义一个队列q,其元素类型应为整型int q[MaxLength]={0};//定义队首和队尾指针int front=0,rear=0;//访问初始点vicout<<g[i]<<':'<<i<<"  ";//标记初始点vi已访问过visited[i]=true;//将已访问过的初始点序号i入队q[++rear]=i;//当队列非空时进行循环处理while(front!=rear) {//删除队首元素,第一次执行时k的值为ifront=(front+1)%MaxLength;int k=q[front];//依次搜索vk的每一个可能的邻接点for(int j=0;j<n;j++)if(k2==0){if(k!=j&&GA[k][j]!=0&&!visited[j]){//访问一个未被访问过的邻接点vjcout<<g[j]<<':'<<j<<"  ";visited[j]=true;     //标记vj已访问过rear=(rear+1)%MaxLength;//顶点序号j入队q[rear]=j;}}elseif(k!=j&&GA[k][j]!=MaxValue&&!visited[j]){//访问一个未被访问过的邻接点vjcout<<g[j]<<':'<<j<<"  ";visited[j]=true;   //标记vj已访问过rear=(rear+1)%MaxLength;//顶点序号j入队q[rear]=j;}
}}
//检查输入的边序号是否越界,若越界则重输
void AdjMatrix::Check(int n,int& i,int& j)
{while(1) {if(i<0||i>=n||j<0||j>=n)cout<<"输入有误,请重输!";else return;cin>>i>>j;}
}
//由图的邻接矩阵得到图的邻接表
void AdjMatrix::graphChange(adjlist &GL,int n,int k2)
{int i,j;if(k2==0){for(i=0;i<n;i++){for(j=0;j<n;j++)if(GA[i][j]!=0) {edgenode* p=new edgenode;p->adjvex=j;p->next=GL[i];GL[i]=p;cout<<'('<<i<<','<<p->adjvex<<") ";}cout<<endl;}}else {for(i=0;i<n;i++){for(j=0;j<n;j++)if(GA[i][j]!=0 && GA[i][j]!=MaxValue) {edgenode* p=new edgenode;p->adjvex=j;p->weight=GA[i][j];p->next=GL[i];GL[i]=p;cout<<'('<<i<<','<<p->adjvex<<','<<p->weight<<") ";}cout<<endl;}
}}
//由图的邻接矩阵建立图
void AdjMatrix::Creatgraph(int n,int k2)
{int i,j,k,m=0;if(k2==0){for(i=0;i<n;i++){k=i;for(j=0;j<n;j++)if(GA[i][j]!=0)if(k==i&&m<n){g[m]='A'+m;size++;cout<<g[m]<<'('<<i<<','<<j<<") ";m++;}}cout<<endl;}else {for(i=0;i<n;i++){k=i;for(j=0;j<n;j++)if(GA[i][j]!=0 && GA[i][j]!=MaxValue)if(k==i&&m<n){g[m]='A'+m;size++;cout<<g[m]<<'('<<i<<','<<j<<','<<GA[i][j]<<") ";m++;}}cout<<endl;}g[n]='\0';
}
//取顶点i的值
char AdjMatrix::GetValue(const int i)
{if(i<0||i>size){cerr<<"参数i越界!\n";exit(1);}return g[i];
}
//取弧<v1,v2>的权
int AdjMatrix::GetWeight(const int v1,const int v2)
{if(v1<0||v1>size||v2<0||v2>size){cerr<<"参数v1或v2越界!\n";exit(1);}return GA[v1][v2];
}
//在位置pos处插入顶点V
void AdjMatrix::InsertV(const char &V,int pos)
{int i;if(size==MaxV){cerr<<"表已满,无法插入!\n";exit(1);}if(pos<0||pos>size){cerr<<"参数pos越界!\n";exit(1);}for(i=size;i>pos;i--) g[i]=g[i-1];g[pos]=V;size++;
}
//插入弧<v1,v2>,权为weight
void AdjMatrix::InsertEdge(const int v1,const int v2,int weight)
{if(v1<0||v1>size||v2<0||v2>size){cerr<<"参数v1或v2越界!\n";exit(1);}GA[v1][v2]=weight;numE++;
}
//删除顶点v与顶点v相关的所有边
char AdjMatrix::DeleteVE(const int v)
{for(int i=0;i<size;i++)for(int j=0;j<size;j++)if((i==v||j==v)&&GA[i][j]>0&&GA[i][j]<MaxValue){GA[i][j]=MaxValue;numE--;}if(size==0){cerr<<"表已空,无元素可删!\n";exit(1);}if(v<0||v>size-1){cerr<<"参数v越界!\n";exit(1);}char temp=g[v];for(int i=v;i<size-1;i++) g[i]=g[i+1];size--;g[size]='\0';return temp;
}
//删除弧<v1,v2>
void AdjMatrix::DeleteEdge(const int v1,const int v2)
{if(v1<0||v1>size||v2<0||v2>size||v1==v2){cerr<<"参数v1或v2出错!\n";exit(1);}GA[v1][v2]=MaxValue;numE--;
}
//对非连通图进行深度优先搜索
void AdjMatrix::dfsMatrix(int n,int k2)
{bool *vis=new bool[NumV()];for(int i=0;i<NumV();i++) vis[i]=false;for(int i=0;i<NumV();i++)if(!vis[i]) dfsMatrix(vis,i,n,k2);delete []vis;
}
//对非连通图进行广度优先搜索
void AdjMatrix::bfsMatrix(int n,int k2)
{bool *vis=new bool[NumV()];for(int i=0;i<NumV();i++) vis[i]=false;for(int i=0;i<NumV();i++)if(!vis[i]) bfsMatrix(vis,i,n,k2);delete []vis;
}

代码调用如下

#include "stdafx.h"#include "graph.h"
//网G从下标v0到其他顶点的最短距离dist和最短路径下标path
void PShortPath(AdjMatrix &G,int v0,int dist[],int path[])
{int n=G.NumV();
int *s=new int[n];
int mindis,i,j,u;
for(i=0;i<n;i++)
{dist[i]=G.GetWeight(v0,i);
s[i]=0;
if(i!=v0&&dist[i]<MaxValue) path[i]=v0;
else path[i]=-1;
}
s[v0]=1;//标记顶点v0已从集合T加入到集合S中
//在当前还未找到最短路径的顶点集中选取具有最短距离的顶点u
for(i=1;i<n;i++)
{mindis=MaxValue;
for(j=0;j<n;j++)
if(s[j]==0&&dist[j]<mindis)
{u=j;
mindis=dist[j];
}
//当已不再存在路径时算法结束;此语句对非连通图是必需的
if(mindis==MaxValue) return;
s[u]=1;//标记顶点u已从集合T加入到集合S中
//修改从v0到其他顶点的最短距离和最短路径
for(j=0;j<n;j++)
if(s[j]==0&&G.GetWeight(u,j)<MaxValue&&dist[u]+G.GetWeight(u,j)<dist[j])
{//顶点v0经顶点u到其他顶点的最短距离和最短路径dist[j]=dist[u]+G.GetWeight(u,j);path[j]=u;
}
}
}
//算法测试
void main()
{cout<<"运行结果:\n";
int n=6,k1=1,k2=1;
AdjMatrix g(n,k2);
g.CreateMatrix(n,k1,k2);
cout<<"\n输出邻接矩阵相应图的每个顶点:\n";
g.Creatgraph(n,k2);
int m=g.NumV();
int *dist=new int[m];
int *path=new int[m];
int v0=0;
PShortPath(g,v0,dist,path);
cout<<"从顶点"<<g.GetValue(v0)
<<"到其他各顶点的最短距离为:\n";
for(int i=0;i<m;i++)
cout<<"到顶点"<<g.GetValue(i)
<<"的最短距离为:"<<dist[i]<<endl;
cout<<"从顶点"<<g.GetValue(v0)
<<"到其他各顶点的最短路径的前一顶点为:\n";
for(int i=0;i<m;i++)
if(path[i]!=-1)
cout<<"到顶点"<<g.GetValue(i)<<"的前一顶点为:"
<<g.GetValue(path[i])<<endl;
cin.get();cin.get();
}

效果如下

代码下载如下

http://download.csdn.net/detail/yincheng01/4789963

转载于:https://www.cnblogs.com/new0801/archive/2012/11/20/6177636.html

VC++2012编程演练数据结构《31》狄杰斯特拉算法相关推荐

  1. VC++2012编程演练数据结构《3》堆栈实现进制转换

    栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表.它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出 ...

  2. VC++2012编程演练数据结构《12》二叉排序树

    二叉排序树(Binary Sort Tree)又称二叉查找树. 它或者是一棵空树:或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值: (2)若右子树不空,则 ...

  3. VC++2012编程演练数据结构《35》多路平衡归并

    多路平衡归并 一般说来,如果初始归并段有m个,那么这样的二路归并树就有élog2mù+1层,要对数据进行élog2mù遍扫描.采用k路平衡归并时,则相应的归并树有élogkmù+1层,要对数据进行él ...

  4. VC++2012编程演练数据结构《25》线索二叉树

    线索二叉树 按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列.在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结点. ...

  5. VC++2012编程演练数据结构《36》磁盘文件进行排序

    如何给磁盘文件排序 问题描述: 输入:一个最多含有n个不相同的正整数的文件,其中每个数都小于等于n,且n=10^7. 输出:得到按从小到大升序排列的包含所有输入的整数的列表. 条件:最多有大约1MB的 ...

  6. VC++2012编程演练数据结构《9》平衡二叉搜索树

    平衡二叉搜索树 任何结点的左子树和右子树高度最多相差1的二叉搜索树. (1)AVL树的插入算法 a. 插入结点之后仍然是AVL树,则不调整: b. 插入结点之后不再满足AVL树条件,则进行调整,根据导 ...

  7. c++ 单源最短路径-狄杰斯特拉算法

    文章目录 源码 输出 狄杰斯特拉算法 适用范围:没有负权重的图, 可以有环,有向无向图均可 求解问题:单源最短路径 时间复杂度:V^2 源码 #include <iostream> #in ...

  8. 最短路径算法---狄杰斯特拉算法

    最短路径算法-狄杰斯特拉算法 一.介绍 这是一种按照路径长度递增的次序产生最短路径的算法,采用的是贪心的思想,对带权图(有向和无向均可)寻找最短路径;该算法对于不含负权的网来说,是目前已知的最快的单源 ...

  9. C++狄杰斯特拉算法(Dijkstra)实现最短路问题

    狄杰斯特拉算法(Dijkstra): 基本思想: 看不懂?没关系,i哲来带你通过具体问题理解这个算法 问题描述: 找出从商家到学校的最短路径 多组输入,对于每组数据. 第一行输入N,M,分别表示大街上 ...

最新文章

  1. UITextField的代理方法
  2. 【Python爬虫学习笔记4】结合Xpath与lxml库解析数据
  3. 学习jvm(一)--java内存区域
  4. java spark读写hdfs_Spark读取HDFS数据输出到不同的文件
  5. Linux格式化分区的命令
  6. python中当地时间_R 与 Python 中与时间相关内容的梳理
  7. MySQL8.0.17 - 初探 Clone Plugin
  8. linux刷脚本需要什么工具吗,利用宝塔Linux一键挂载脚本工具挂载www目录方法
  9. 2018热度上升最快的编程工具是什么?TensorFlow只排第11
  10. python object和type的关系-Python 的 type 和 object 之间是怎么一种关系?
  11. S3VM和TSVM的不同
  12. 政考网:怎样考取公务员上岸?
  13. Reflex WMS入门系列七:收货(Receipt)
  14. python 邮件抄送是什么意思_python使用SMTP发邮件时使用Cc(抄送)和Bcc(密送)...
  15. java 支付宝 验证签名失败,关于支付宝签名校验失败的问题排解
  16. 奇偶性与魔术(一)——奇偶性的数学本质
  17. iOS系统自带指纹验证的使用
  18. 把汉字转换成拼音的util
  19. sklearn模块之朴素贝叶斯:(二)伯努利模型的实现
  20. 黑鲨helo支持html吗,黑鲨2和黑鲨helo区别买哪个好

热门文章

  1. C# 弹出输入框取值
  2. 网站解析 选择 主记录www 为主站 记录类型都选A 泛解析 选*就好了
  3. Spring Cloud with Turbine
  4. 解决freebsd下root默认不能用ssh连接
  5. MyEclipse 2014下搭建Android开发环境
  6. Linux远程桌面工具Xming+Putty的搭建
  7. 云服务和硬件成微软业绩新增长点
  8. xdebug断点调试原理
  9. 无刷新三级联动(ajax)(转)
  10. 服务器上使用 git 更新 wordpress 内核方案