单源最短路径—Bellman-Ford和Dijkstra算法
Bellman-Ford算法:通过对边进行松弛操作来渐近地降低从源结点s到每个结点v的最短路径的估计值v.d,直到该估计值与实际的最短路径权重相同时为止。该算法主要是基于下面的定理:
设G=(V,E)是一带权重的源结点为s的有向图,其权重函数为W,假设图G中不包含从源结点s可到达的权重为负值的环路,在对图中的每条边执行|V|-1次松弛之后,对于所有从源结点s可到达的结点v,都有。
证明:s可到达结点v并且图中没有权重为负值的环路,所以总能找到一条路径p=(v0,v1,...,vk)是从s到v结点的最短路径,这里v0=s,vk=v。因为最短路径都是简单路径,p最多包含|V|-1条边,即k<=|V|-1。由于v0=s,所以,当对所有的边进行第1次松弛后,必有
,依次类推,进行第k次松弛后,必有
,最后可得进行|V|-1次松弛后有
下面证明为什么当,对边
松弛后,有:
。
由于s->...->vi-1->vi是一条最短路径,在对边松弛后,
有:(这个是松弛的定义)。
又由于,所以:
。
Bellman-Ford算法的实现是对图中的每条边进行|V|-1次松弛。
Dijkstra算法:将图中的结点分为两类,一类是结点集合S,从源结点s到集合中每个结点之间的最短路径已经被找到。另一类集合是V-S。算法重复地从集合V-S中选择最短路径估计最小的结点u,然后将u加入到集合S,然后对所有从u出发的边进行松弛。在进行|V|次重复操作后,其中每条边经历过一次松弛,对于所有的结点v,都有。关键点是证明:该算法在每次选择结点u来加入到集合S时,有
。证明过程省略,可以参考《算法导论》的证明过程。
下面给两种算法的出程序:在Dijkstra算法中,通过结点的颜色color来区分结点是属于S集合还是V-S集合,黑色时是S集合中,白色时是V-S集合中
Minpath.h
#pragma once
#include<iostream>
#include<string>
#include<vector>
using namespace std; template<typename Comparable>
struct Edge;
template<typename Comparable>
struct Node
{
Comparable element;//结点的元素
vector<Edge<Comparable>*>Side;//该结点所在的边
Node<Comparable>* T; //最短路径中该结点的父亲
int dis; //距离
string color; //在Dijkstra算法中用于标记该结点是否被选中
Node(Comparable e,Node<Comparable>* f,int d,string c)
{
element=e;
T=f;
dis=d;
color=c;
}
};
template<typename Comparable>
struct Edge
{
Node<Comparable>* N1; //边的两端结点,N1是N2结点的父结点
Node<Comparable>* N2;
string color;
int weight;
Edge(Node<Comparable>* n1,Node<Comparable>* n2,int w):N1(n1),N2(n2),weight(w){}
}; template<typename Comparable>
class graph
{
public:
void insert(Comparable *a,int *matrix,int *w,int n);//a:图中个结点的元素;matrix:邻接矩阵
void Bellman(Comparable x);
void Dijkstra(Comparable x);
void MinPath(Comparable x);
private:
vector<Node<Comparable>*> root;
vector<Edge<Comparable>*> side;
Node<Comparable>* find(Comparable x);
Node<Comparable>* find();
void relax(Edge<Comparable>* edge); //松弛
void MinPath(Node<Comparable>* s);
};
Minpath.cpp
#include "stdafx.h"
#include"Minpath.h"
#include<iostream>
#include<string>
#include<vector>
using namespace std; template<typename Comparable>
void graph<Comparable>::insert(Comparable *a,int *matrix,int *w,int n)
{
for(int i=0;i<n;i++)
{
Node<Comparable>* node=new Node<Comparable>(a[i],NULL,10000,"WHITE");
root.push_back(node);
}
Node<Comparable>* node=NULL;
Node<Comparable>* temp=NULL;
int k=0;
for(int i=0;i<n;i++)
{
node=root[i];
for(int j=0;j<n;j++)
{
if(matrix[n*i+j]!=0)
{
temp=root[j];
Edge<Comparable>* edge=new Edge<Comparable>(node,temp,w[k]);
k=k+1;
side.push_back(edge);
node->Side.push_back(edge);
}
}
}
}
//找出元素是x的结点
template<typename Comparable>
Node<Comparable>* graph<Comparable>::find(Comparable x)
{
int n=root.size();
Node<Comparable>* temp=NULL;
for(int i=0;i<n;i++)
{
if(root[i]->element==x)
temp=root[i];
}
return temp;
}
//边的松弛
template<typename Comparable>
void graph<Comparable>::relax(Edge<Comparable>* edge)
{
if(edge->N2->dis>edge->N1->dis+edge->weight)
{
edge->N2->dis=edge->N1->dis+edge->weight;
edge->N2->T=edge->N1;
} }
//Bellman-Ford算法:对图中的边进行|v|-1次的松弛
template<typename Comparable>
void graph<Comparable>::Bellman(Comparable x)
{
Node<Comparable>* s=find(x);
bool flag=true;
if(s==NULL)
return;
int n=root.size();
int en=side.size();
Edge<Comparable>* edge=NULL;
s->dis=0; //选择s为源结点,并初始化其距离为0
//对图中的每个边进行|V|-1次的松弛
for(int i=0;i<n-1;i++)
{
for(int j=0;j<en;j++)
{
edge=side[j];
relax(edge); //松弛
}
}
for(int i=0;i<en;i++)
{
edge=side[i];
if(edge->N2->dis>edge->N1->dis+edge->weight)
flag=false;
} if(flag==false)
cout<<"图中包含权重为负值的环路"<<endl;
else
{
s->T=NULL;
} }
//Dijkstra算法
template<typename Comparable>
void graph<Comparable>::Dijkstra(Comparable x)
{
Node<Comparable>* s=find(x);
Node<Comparable>* source=s;
if(s==NULL)
return;
Edge<Comparable>* edge=NULL;
Node<Comparable>* temp=new Node<Comparable>(s->element,NULL,10000,"WHITE");
Node<Comparable>* t=temp;
int n=root.size(); s->dis=0;
s->color="BLACK"; //初始化源结点 for(int i=0;i<n;i++)
{
int en=s->Side.size();
for(int j=0;j<en;j++) //对s结点的所有的边进行一次松弛
{
edge=s->Side[j];
relax(edge);
}
s=find();
s->color="BLACK";
}
source->T=NULL;
}
template<typename Comparable>
Node<Comparable>* graph<Comparable>::find()
{
Node<Comparable>* s=new Node<Comparable>(root[0]->element,NULL,10000,"WHITE");
int n=root.size();
for(int i=0;i<n;i++)
{
if((root[i]->color=="WHITE")&&(root[i]->dis<s->dis))
s=root[i];
}
return s;
}
//找出某结点的最短路径并输出
template<typename Comparable>
void graph<Comparable>::MinPath(Comparable x)
{
Node<Comparable>* s=find(x);
cout<<"最短路径为:"<<endl;
MinPath(s->T);
cout<<"("<<s->element<<","<<s->dis<<")"<<endl;
}
template<typename Comparable>
void graph<Comparable>::MinPath(Node<Comparable>* s)
{
if(s!=NULL)
{
MinPath(s->T);
cout<<"("<<s->element<<","<<s->dis<<")"<<"—>";
}
else
return;
}
Algorithm-graph3.cpp
// Algorithm-graph3.cpp : 定义控制台应用程序的入口点。
//主要是图中的最短路径问题:Bellman-Ford算法和Dijkstra算法 #include "stdafx.h"
#include"Minpath.h"
#include"Minpath.cpp"
#include<iostream>
#include<string>
#include<vector>
using namespace std;
#include<iostream> int _tmain(int argc, _TCHAR* argv[])
{
graph<string> g;
////Bellman-Ford算法
/* int n=5;
int matrix[25]={0,1,0,0,1,
0,0,1,1,1,
0,1,0,0,0,
1,0,1,0,0,
0,0,1,1,0};
string a[5]={"s","t","x","z","y"};
int w[10]={6,7,5,-4,8,-2,2,7,-3,9};*/ //Dijkstra算法
int n=5;
int matrix[25]={0,1,0,0,1,
0,0,1,0,1,
0,0,0,1,0,
1,0,1,0,0,
0,1,1,1,0};
string a[5]={"s","t","x","z","y"};
int w[10]={10,5,1,2,4,7,6,3,9,2};
g.insert(a,matrix,w,n);
// g.Bellman("s");
g.Dijkstra("s"); //选择结点元素为s的作为源结点
g.MinPath("x"); //输出结点元素是x的最短路径
return 0;
}
单源最短路径—Bellman-Ford和Dijkstra算法的更多相关文章
- 单源最短路径-迪杰斯特拉算法(Dijkstra's algorithm)
Dijkstra's algorithm 迪杰斯特拉算法是目前已知的解决单源最短路径问题的最快算法. 单源(single source)最短路径,就是从一个源点出发,考察它到任意顶点所经过的边的权重之 ...
- matlab练习程序(单源最短路径Bellman-Ford)
该算法可以用来解决一般(边的权值为负)的单源最短路径问题,而dijkstra只能解决权值非负的情况. 此算法使用松弛技术,对每一个顶点,逐步减少源到该顶点的路径的估计值,直到达到最短的路径. 算法运算 ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- 单源最短路径算法---Dijkstra
Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路 ...
- Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 32824 Accepted: 11098 Description Bes ...
- 单源最短路径——dijkstra算法
dijkstra算法与prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...
- 【转】Dijkstra算法(单源最短路径)
原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...
- 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法
Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...
- 单源最短路径(dijkstra算法)php实现
做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...
- Dijkstra算法——单源最短路径问题
学习一个点到其余各个顶点的最短路径--单源最短路径 Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向 ...
随机推荐
- thinkphp连接mysql5.5版本数据库
//数据库配置信息 'DB_TYPE' => 'mysqli', // 数据库类型 'DB_HOST' => 'localhost', // 服务器地址 'DB_NAME' => ' ...
- 第23讲 UI_布局 之相对布局
第23讲 UI_布局 之相对布局 .RelativeLayout(相对布局): RelativeLayout(相对布局)是指组件的位置总是相对兄弟组件.父容器来决定的(相对位置),如某个组件的左边右边 ...
- Laravel-路由-控制器
(慕课网_轻松学会Laravel-基础篇_天秤vs永恒老师) 一.基础路由 二.多请求路由 三.参数路由 四.路由别名 生成url可以使用别名 五.路由群组 六.路由输出视图 七.控制器参数绑定
- oracle 使用sql获取数据库表,表的字段
--第一种方法: 查询dba_tab_columns select COLUMN_NAME,DATA_TYPE,DATA_LENGTH from dba_tab_columns where t ...
- BuguMongo是一个MongoDB Java开发框架,集成了DAO、Query、Lucene、GridFS等功能
http://code.google.com/p/bugumongo/ 简介 BuguMongo是一个MongoDB Java开发框架,它的主要功能包括: 基于注解的对象-文档映射(Object-Do ...
- atitit。自己定义uml MOF EMF体系eclipse emf 教程o7t
atitit.自己定义uml MOF EMF体系eclipse emf 教程o7t 1. 元对象机制(MOF,Meta-Object Facility)and 结构 1 2. 元模型图.模型图.对 ...
- line-hight-(行高)解析
行高定义:line-height属性是指文本行基线之间的距离. 顶线.中线.基线.底线概念 从上到下四条线分别是顶线.中线.基线.底线,很像才学英语字母时的四线三格,我们知道vertical-alig ...
- (转)SQL Server2005 异常处理机制(Begin try Begin Catch)
begin try --SQL end trybegin catch --sql (处理出错动作) end catch我们将可能会出错的sql 写在begin try...end try 之间,若出 ...
- Homebrew -- Mac软件管家(套件管理yun……)
也许是之前使用linux系统的时候总是习惯使用wget 在mac中只有curl,有点略显不习惯 于是乎某天在搜索mac开发者的时候发现了Homebrew这个东西 ok,是那么句话--惰性是人的天性 有 ...
- Lightoj1009 Back to Underworld(带权并查集)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Back to Underworld Time Limit:4000MS ...