本代码为算法导论24.1的C++实现。
#include <iostream>
using namespace std;
#define N 5
#define INFINITE 0x7fffffff
#define WHITE 1
#define GRAY 2
#define BLACK 3
//顶点结点结构
struct Vertex
{
Vertex * next;/*指向下一个顶点*/
int id;/*节点的标志*/
int weight;/*节点的权值,临界表表头到此元素上边的权值*/
Vertex():next(NULL),id(0){}
};
//图结构
struct Graph
{
Vertex *Adj[N+1];//N个顶点及邻接点头指针
int p[N+1];//指向遍历树节点的父结点
int d[N+1];/*节点的最短路径权值的上界*/
Graph()
{
for(int i = 1; i <= N; i++)
{
Adj[i] = new Vertex;
d[i] = 0;
p[i] = 0;
}
}
~Graph()
{
for(int i = 1; i <= N; i++)
delete Adj[i];
}
};
void Print(Graph *g);
bool Init(Graph *g);
bool InsertEdge(Graph *g , int start,int end,int weight);
bool InitializeSingleSource(Graph *g,int s);
bool Relax(Graph *g,int u,int v,int weight);
bool Relax(Graph *g,int u,int v);
int Weight(const Graph *g,int u,int v);
/*
start边开始节点,end边结束节点,weight边权值
*/
//插入边
bool InsertEdge(Graph *g , int start,int end,int weight)
{
Vertex* v = new Vertex();
v->id = end;
v->weight = weight;
if(g->Adj[start]->next == NULL)
{/*如果不存在临界表的头结点列表中,则插入*/
Vertex* s = new Vertex();
s->id = start;
g->Adj[start] = s;
}
Vertex* tmp = g->Adj[start];
while(tmp->next)
{
tmp = tmp->next;
}
tmp->next =v;
return true;
}
/*初始化临接表表示的图,有向图。
*/
bool Init(Graph *g)
{
InsertEdge(g,1,2,6);
InsertEdge(g,1,4,7);
InsertEdge(g,2,3,5);
InsertEdge(g,2,4,8);
InsertEdge(g,2,5,-4);
InsertEdge(g,3,2,-2);
InsertEdge(g,4,3,-3);
InsertEdge(g,4,5,9);
InsertEdge(g,5,1,2);
InsertEdge(g,5,3,7);
return true;
}
/*取得两个两个节点连接的边的权重*/
int Weight(const Graph *g,int u,int v)
{
Vertex * t = g->Adj[u]->next;
while(t)
{
if(t->id == v)
{
return t->weight;
}
t = t->next;
}
return 0;
}
bool Relax(Graph *g,int u,int v,int weight)
{
if(g->d[v] > (g->d[u] + Weight(g,u,v)))
{
g->d[v] = g->d[u] + Weight(g,u,v);
g->p[v] = u;
}
return true;
}
/*对边进行松弛操作*/
bool Relax(Graph *g,int u,int v)
{
Relax(g,u,v,Weight(g,u,v));
return false;
}
/*
最短路径估计和前驱化进行初始化
s 源顶点
*/
bool InitializeSingleSource(Graph *g,int s)
{
for(int i=1;i<=N;i++)
{
g->d[i] = INFINITE;
g->p[i] = 0;
}
g->d[s] = 0;
return true;
}
/*单源最短路径的Bellman-Ford算法*/
bool BellmanFord(Graph *g,int s)
{
InitializeSingleSource(g,s);
for(int i=1;i<N;i++)
{/*对每个边进行N-1次松弛操作*/
for(int j=1;j<=N;j++)
{
Vertex * t = g->Adj[j]->next;
while(t)
{
Relax(g,j,t->id);
t = t->next;
}
}
}
for(int i=1;i<=N;i++)
{/*如果包含从原点可达的负权回路,返回FALSE*/
Vertex * t = g->Adj[i]->next;
while(t)
{
if(g->d[t->id] > (g->d[i] + Weight(g,i,t->id)))
{
return false;
}
t = t->next;
}
}
return true;
}
/*
开始顶点 1
顶点 最短路径
1 0
2 2
3 4
4 7
5 -2
*/
int main(int argc,char * argv[])
{
//构造一个空的图
Graph *g = new Graph;
Init(g);
BellmanFord(g,1);
for(int i=1;i<=N;i++)
{
std::cout<<i<<"\t"<<g->d[i]<<std::endl;
}
delete g;
getchar();
return 0;
}