【算法导论】24.1 Bellman-Ford 算法

本代码为算法导论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;
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/harry_lyc/article/details/8199507
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞